Skip to content

Commit 72dc550

Browse files
committed
Enable using handlers with mapper interfaces.
1 parent b95783e commit 72dc550

File tree

7 files changed

+154
-4
lines changed

7 files changed

+154
-4
lines changed

src/main/java/org/apache/ibatis/binding/MapperMethod.java

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.apache.ibatis.mapping.MappedStatement;
1212
import org.apache.ibatis.mapping.SqlCommandType;
1313
import org.apache.ibatis.session.Configuration;
14+
import org.apache.ibatis.session.ResultHandler;
1415
import org.apache.ibatis.session.RowBounds;
1516
import org.apache.ibatis.session.SqlSession;
1617

@@ -27,8 +28,10 @@ public class MapperMethod {
2728

2829
private boolean returnsList;
2930
private boolean returnsMap;
31+
private boolean returnsVoid;
3032
private String mapKey;
3133

34+
private Integer resultHandlerIndex;
3235
private Integer rowBoundsIndex;
3336
private List<String> paramNames;
3437
private List<Integer> paramPositions;
@@ -50,7 +53,7 @@ public MapperMethod(Class<?> declaringInterface, Method method, SqlSession sqlSe
5053
}
5154

5255
public Object execute(Object[] args) {
53-
Object result;
56+
Object result = null;
5457
if (SqlCommandType.INSERT == type) {
5558
Object param = getParam(args);
5659
result = sqlSession.insert(commandName, param);
@@ -61,7 +64,9 @@ public Object execute(Object[] args) {
6164
Object param = getParam(args);
6265
result = sqlSession.delete(commandName, param);
6366
} else if (SqlCommandType.SELECT == type) {
64-
if (returnsList) {
67+
if (returnsVoid && resultHandlerIndex != null) {
68+
executeWithResultHandler(args);
69+
} else if (returnsList) {
6570
result = executeForList(args);
6671
} else if (returnsMap) {
6772
result = executeForMap(args);
@@ -75,6 +80,16 @@ public Object execute(Object[] args) {
7580
return result;
7681
}
7782

83+
private void executeWithResultHandler(Object[] args) {
84+
Object param = getParam(args);
85+
if (rowBoundsIndex != null) {
86+
RowBounds rowBounds = (RowBounds) args[rowBoundsIndex];
87+
sqlSession.select(commandName, param, rowBounds, (ResultHandler) args[resultHandlerIndex]);
88+
} else {
89+
sqlSession.select(commandName, param, (ResultHandler) args[resultHandlerIndex]);
90+
}
91+
}
92+
7893
private List executeForList(Object[] args) {
7994
List result;
8095
Object param = getParam(args);
@@ -121,6 +136,9 @@ private void setupFields() {
121136
}
122137

123138
private void setupMethodSignature() {
139+
if( method.getReturnType().equals(Void.TYPE)){
140+
returnsVoid = true;
141+
}
124142
if (List.class.isAssignableFrom(method.getReturnType())) {
125143
returnsList = true;
126144
}
@@ -135,7 +153,17 @@ private void setupMethodSignature() {
135153
final Class<?>[] argTypes = method.getParameterTypes();
136154
for (int i = 0; i < argTypes.length; i++) {
137155
if (RowBounds.class.isAssignableFrom(argTypes[i])) {
138-
rowBoundsIndex = i;
156+
if (rowBoundsIndex == null) {
157+
rowBoundsIndex = i;
158+
} else {
159+
throw new BindingException(method.getName() + " cannot have multiple RowBounds parameters");
160+
}
161+
} else if (ResultHandler.class.isAssignableFrom(argTypes[i])) {
162+
if (resultHandlerIndex == null) {
163+
resultHandlerIndex = i;
164+
} else {
165+
throw new BindingException(method.getName() + " cannot have multiple ResultHandler parameters");
166+
}
139167
} else {
140168
String paramName = String.valueOf(paramPositions.size());
141169
paramName = getParamNameFromAnnotation(i, paramName);

src/main/java/org/apache/ibatis/binding/MapperProxy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
3636
final Class<?> declaringInterface = findDeclaringInterface(proxy, method);
3737
final MapperMethod mapperMethod = new MapperMethod(declaringInterface, method, sqlSession);
3838
final Object result = mapperMethod.execute(args);
39-
if (result == null && method.getReturnType().isPrimitive()) {
39+
if (result == null && method.getReturnType().isPrimitive() && !method.getReturnType().equals(Void.TYPE)) {
4040
throw new BindingException("Mapper method '" + method.getName() + "' (" + method.getDeclaringClass() + ") attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
4141
}
4242
return result;

src/test/java/domain/blog/mappers/AuthorMapper.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@
44

55
import java.util.List;
66

7+
import org.apache.ibatis.session.ResultHandler;
8+
79
public interface AuthorMapper {
810

911
List selectAllAuthors();
12+
13+
void selectAllAuthors(ResultHandler handler);
1014

1115
Author selectAuthor(int id);
1216

17+
void selectAuthor(int id, ResultHandler handler);
18+
1319
void insertAuthor(Author author);
1420

1521
int deleteAuthor(int id);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package domain.blog.mappers;
2+
3+
import org.apache.ibatis.annotations.Select;
4+
import org.apache.ibatis.session.ResultHandler;
5+
6+
public interface AuthorMapperWithMultipleHandlers {
7+
@Select("select id, username, password, email, bio, favourite_section from author where id = #{id}")
8+
void selectAuthor(int id, ResultHandler handler1, ResultHandler handler2);
9+
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package domain.blog.mappers;
2+
3+
import org.apache.ibatis.annotations.Select;
4+
import org.apache.ibatis.session.RowBounds;
5+
6+
public interface AuthorMapperWithRowBounds {
7+
@Select("select id, username, password, email, bio, favourite_section from author where id = #{id}")
8+
void selectAuthor(int id, RowBounds bounds1, RowBounds bounds2);
9+
10+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package domain.blog.mappers;
2+
3+
import domain.blog.Author;
4+
5+
import java.util.List;
6+
7+
import org.apache.ibatis.session.ResultHandler;
8+
9+
public interface CopyOfAuthorMapper {
10+
11+
List selectAllAuthors();
12+
13+
void selectAllAuthors(ResultHandler handler);
14+
15+
Author selectAuthor(int id);
16+
17+
void selectAuthor(int id, ResultHandler handler);
18+
19+
void insertAuthor(Author author);
20+
21+
int deleteAuthor(int id);
22+
23+
int updateAuthor(Author author);
24+
25+
}
26+
27+
28+

src/test/java/org/apache/ibatis/session/SqlSessionTest.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,20 @@
22

33
import domain.blog.*;
44
import domain.blog.mappers.AuthorMapper;
5+
import domain.blog.mappers.AuthorMapperWithMultipleHandlers;
6+
import domain.blog.mappers.AuthorMapperWithRowBounds;
57
import domain.blog.mappers.BlogMapper;
68
import org.apache.ibatis.BaseDataTest;
9+
import org.apache.ibatis.binding.BindingException;
710
import org.apache.ibatis.cache.impl.PerpetualCache;
11+
import org.apache.ibatis.exceptions.PersistenceException;
12+
import org.apache.ibatis.executor.result.DefaultResultHandler;
813
import org.apache.ibatis.io.Resources;
14+
import org.apache.ibatis.mapping.Environment;
15+
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
16+
917
import static org.junit.Assert.*;
18+
1019
import org.junit.BeforeClass;
1120
import org.junit.Test;
1221

@@ -476,6 +485,65 @@ public void shouldExecuteSelectOneAuthorUsingMapperClass() {
476485
}
477486
}
478487

488+
@Test
489+
public void shouldExecuteSelectOneAuthorUsingMapperClassWithResultHandler() {
490+
SqlSession session = sqlMapper.openSession();
491+
try {
492+
DefaultResultHandler handler = new DefaultResultHandler();
493+
AuthorMapper mapper = session.getMapper(AuthorMapper.class);
494+
mapper.selectAuthor(101, handler);
495+
Author author = (Author) handler.getResultList().get(0);
496+
assertEquals(101, author.getId());
497+
} finally {
498+
session.close();
499+
}
500+
}
501+
502+
@Test
503+
public void shouldSelectAuthorsUsingMapperClassWithResultHandler() {
504+
SqlSession session = sqlMapper.openSession();
505+
try {
506+
DefaultResultHandler handler = new DefaultResultHandler();
507+
AuthorMapper mapper = session.getMapper(AuthorMapper.class);
508+
mapper.selectAllAuthors(handler);
509+
assertEquals(2, handler.getResultList().size());
510+
} finally {
511+
session.close();
512+
}
513+
}
514+
515+
@Test(expected = BindingException.class)
516+
public void shouldFailSelectOneAuthorUsingMapperClassWithTwoResultHandlers() {
517+
Configuration configuration = new Configuration(sqlMapper.getConfiguration().getEnvironment());
518+
configuration.addMapper(AuthorMapperWithMultipleHandlers.class);
519+
SqlSessionFactory sqlMapperWithMultipleHandlers = new DefaultSqlSessionFactory(configuration);
520+
SqlSession sqlSession = sqlMapperWithMultipleHandlers.openSession();
521+
try {
522+
DefaultResultHandler handler1 = new DefaultResultHandler();
523+
DefaultResultHandler handler2 = new DefaultResultHandler();
524+
AuthorMapperWithMultipleHandlers mapper = sqlSession.getMapper(AuthorMapperWithMultipleHandlers.class);
525+
mapper.selectAuthor(101, handler1, handler2);
526+
} finally {
527+
sqlSession.close();
528+
}
529+
}
530+
531+
@Test(expected = BindingException.class)
532+
public void shouldFailSelectOneAuthorUsingMapperClassWithTwoRowBounds() {
533+
Configuration configuration = new Configuration(sqlMapper.getConfiguration().getEnvironment());
534+
configuration.addMapper(AuthorMapperWithRowBounds.class);
535+
SqlSessionFactory sqlMapperWithMultipleHandlers = new DefaultSqlSessionFactory(configuration);
536+
SqlSession sqlSession = sqlMapperWithMultipleHandlers.openSession();
537+
try {
538+
RowBounds bounds1 = new RowBounds(0, 1);
539+
RowBounds bounds2 = new RowBounds(0, 1);
540+
AuthorMapperWithRowBounds mapper = sqlSession.getMapper(AuthorMapperWithRowBounds.class);
541+
mapper.selectAuthor(101, bounds1, bounds2);
542+
} finally {
543+
sqlSession.close();
544+
}
545+
}
546+
479547
@Test
480548
public void shouldInsertAuthorUsingMapperClass() throws Exception {
481549
SqlSession session = sqlMapper.openSession();

0 commit comments

Comments
 (0)