Created
October 5, 2011 01:01
-
-
Save criminy/1263330 to your computer and use it in GitHub Desktop.
Initial MyBatis support for Spring-Data (specifically a sample repository and Pagination).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Collection; | |
import java.util.List; | |
import java.util.ListIterator; | |
import org.springframework.data.domain.PageImpl; | |
import org.springframework.data.domain.Pageable; | |
/** | |
* Extension class between spring data commons and java.util.List that is | |
* required to get MyBatis to use it as a return value. | |
* | |
* The list section is all undefined. | |
* | |
* @author sheenobu | |
* | |
* @param <T> The Type of the contained entity. | |
*/ | |
public class PageI<T> extends PageImpl<T> implements List<T> { | |
public PageI(List<T> content) { | |
super(content); | |
} | |
public PageI(List<T> content,Pageable pageable, int total) { | |
super(content,pageable,total); | |
} | |
private static final long serialVersionUID = 1L; | |
@Override | |
public boolean add(T e) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public void add(int index, T element) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public boolean addAll(Collection<? extends T> c) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public boolean addAll(int index, Collection<? extends T> c) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public void clear() { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public boolean contains(Object o) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public boolean containsAll(Collection<?> c) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public T get(int index) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public int indexOf(Object o) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public boolean isEmpty() { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public int lastIndexOf(Object o) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public ListIterator<T> listIterator() { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public ListIterator<T> listIterator(int index) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public boolean remove(Object o) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public T remove(int index) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public boolean removeAll(Collection<?> c) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public boolean retainAll(Collection<?> c) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public T set(int index, T element) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public int size() { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public List<T> subList(int fromIndex, int toIndex) { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public Object[] toArray() { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public <T> T[] toArray(T[] a) { | |
throw new UnsupportedOperationException(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.Serializable; | |
public class Person implements Serializable{ | |
private static final long serialVersionUID = 1L; | |
private String firstName; | |
private String lastName; | |
private String id; | |
private String username; | |
private String password; | |
public String getFirstName() { | |
return firstName; | |
} | |
public void setFirstName(String firstName) { | |
this.firstName = firstName; | |
} | |
public String getLastName() { | |
return lastName; | |
} | |
public void setLastName(String lastName) { | |
this.lastName = lastName; | |
} | |
public String getId() { | |
return id; | |
} | |
public void setId(String id) { | |
this.id = id; | |
} | |
public String getUsername() { | |
return username; | |
} | |
public void setUsername(String username) { | |
this.username = username; | |
} | |
public String getPassword() { | |
return password; | |
} | |
public void setPassword(String password) { | |
this.password = password; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.List; | |
import org.springframework.data.domain.Pageable; | |
import org.springframework.data.repository.CrudRepository; | |
public interface PersonRepository extends CrudRepository<Person,String> { | |
//all listed are implemented YaY. | |
@Override | |
public long count(); | |
@Override | |
public List<Person> findAll(); | |
@Override | |
public Person findOne(String id); | |
public PageI<Person> findAll(Pageable page); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | |
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
<mapper namespace="PersonRepository"> | |
<select id="findAll" resultType="Person" parameterType="org.springframework.data.domain.Pageable" > | |
SELECT | |
uuid, | |
firstName, | |
lastName, | |
userID as username, | |
password | |
from person | |
<!-- TODO: USE if and foreach for sorting and pagination --> | |
</select> | |
<select id="findOne" resultType="Person" parameterType="String"> | |
SELECT | |
uuid, | |
firstName, | |
lastName, | |
userID as username, | |
password | |
from person | |
where | |
uuid = #{id} | |
</select> | |
<select id="count" resultType="int"> | |
SELECT | |
count(*) | |
from person | |
</select> | |
</mapper> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.sql.ResultSet; | |
import java.sql.Statement; | |
import java.util.List; | |
import java.util.Properties; | |
import org.apache.ibatis.executor.Executor; | |
import org.apache.ibatis.mapping.MappedStatement; | |
import org.apache.ibatis.plugin.Interceptor; | |
import org.apache.ibatis.plugin.Intercepts; | |
import org.apache.ibatis.plugin.Invocation; | |
import org.apache.ibatis.plugin.Plugin; | |
import org.apache.ibatis.plugin.Signature; | |
import org.apache.ibatis.session.ResultHandler; | |
import org.apache.ibatis.session.RowBounds; | |
import org.springframework.data.domain.Pageable; | |
/** | |
* MyBatis plugin which allows functions of the form | |
* | |
* : {@link PageI}<T> someFunction(...,{@link Pageable} pageable,...) | |
* | |
* to work properly using spring-datas {@link Pageable} and {@link Page} interfaces. | |
* | |
* @author sheenobu | |
* | |
*/ | |
//ISSUE 1: bad query transformation. | |
//ISSUE 2: The function must use PageI instead of Page, otherwise mybatis will choke. | |
@Intercepts({ @Signature(type = Executor.class, method = "query", args = | |
{ MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class } )}) | |
public class SpringDataMyBatisPlugin implements Interceptor { | |
@Override | |
public Object intercept(Invocation arg0) throws Throwable { | |
boolean pageable = false; | |
Pageable pageableObject = null; | |
MappedStatement stmt = null; | |
for(Object o : arg0.getArgs()) | |
{ | |
if(o != null) | |
{ | |
if(Pageable.class.isAssignableFrom(o.getClass())) { | |
pageable = true; | |
pageableObject = (Pageable) o; | |
} | |
if(o instanceof MappedStatement) | |
{ | |
stmt = (MappedStatement)o; | |
} | |
} | |
} | |
Object ret = arg0.proceed(); | |
if(pageable && pageableObject != null && stmt != null) { | |
int total = -1; | |
Executor exec = (Executor) arg0.getTarget(); | |
Statement sqlstmt = exec.getTransaction().getConnection().createStatement(); | |
// This is a bit shady. I might want to replace it by finding a similar function on the same | |
// mapper. For example: FunctionA => countOfFunctionA | |
//Convert the select ... from ... statement to a count statement. | |
//TODO: remove paginating LIMITS and such. | |
ResultSet s = sqlstmt.executeQuery(stmt.getSqlSource().getBoundSql(null).getSql().replace('\n', ' ') | |
.replaceFirst("[S|s][E|e][L|l][E|e][C|c][T\t]\\s+.*[F|f][R|r][O|o][M|m]","SELECT count(*) from ")); | |
s.next(); | |
total = s.getShort(1); | |
PageI<?> pi = new PageI<Object>((List)ret, pageableObject,total); | |
return pi; | |
} | |
return ret; | |
} | |
@Override | |
public Object plugin(Object arg0) { | |
return Plugin.wrap(arg0,(Interceptor) this); | |
} | |
@Override | |
public void setProperties(Properties arg0) { | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is this still working with spring boot 1.4 and mybatis 3.4.1 ?