Skip to content

Commit 00fd4ba

Browse files
authored
Merge pull request #1131 from kazuki43zoo/gh-1130
Allow calling a static provider method without instantiation
2 parents 2982c5d + 3994813 commit 00fd4ba

File tree

2 files changed

+120
-4
lines changed

2 files changed

+120
-4
lines changed

src/main/java/org/apache/ibatis/builder/annotation/ProviderSqlSource.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
*/
1616
package org.apache.ibatis.builder.annotation;
1717

18+
import java.lang.reflect.InvocationTargetException;
1819
import java.lang.reflect.Method;
20+
import java.lang.reflect.Modifier;
1921
import java.util.HashMap;
2022
import java.util.Map;
2123

@@ -109,16 +111,16 @@ private SqlSource createSqlSource(Object parameterObject) {
109111
int bindParameterCount = providerMethodParameterTypes.length - (providerContext == null ? 0 : 1);
110112
String sql;
111113
if (providerMethodParameterTypes.length == 0) {
112-
sql = (String) providerMethod.invoke(providerType.newInstance());
114+
sql = invokeProviderMethod();
113115
} else if (bindParameterCount == 0) {
114-
sql = (String) providerMethod.invoke(providerType.newInstance(), providerContext);
116+
sql = invokeProviderMethod(providerContext);
115117
} else if (bindParameterCount == 1 &&
116118
(parameterObject == null || providerMethodParameterTypes[(providerContextIndex == null || providerContextIndex == 1) ? 0 : 1].isAssignableFrom(parameterObject.getClass()))) {
117-
sql = (String) providerMethod.invoke(providerType.newInstance(), extractProviderMethodArguments(parameterObject));
119+
sql = invokeProviderMethod(extractProviderMethodArguments(parameterObject));
118120
} else if (parameterObject instanceof Map) {
119121
@SuppressWarnings("unchecked")
120122
Map<String, Object> params = (Map<String, Object>) parameterObject;
121-
sql = (String) providerMethod.invoke(providerType.newInstance(), extractProviderMethodArguments(params, providerMethodArgumentNames));
123+
sql = invokeProviderMethod(extractProviderMethodArguments(params, providerMethodArgumentNames));
122124
} else {
123125
throw new BuilderException("Error invoking SqlProvider method ("
124126
+ providerType.getName() + "." + providerMethod.getName()
@@ -160,6 +162,14 @@ private Object[] extractProviderMethodArguments(Map<String, Object> params, Stri
160162
return args;
161163
}
162164

165+
private String invokeProviderMethod(Object... args) throws Exception {
166+
Object targetObject = null;
167+
if (!Modifier.isStatic(providerMethod.getModifiers())) {
168+
targetObject = providerType.newInstance();
169+
}
170+
return (String) providerMethod.invoke(targetObject, args);
171+
}
172+
163173
private String replacePlaceholder(String sql) {
164174
return PropertyParser.parse(sql, configuration.getVariables());
165175
}

src/test/java/org/apache/ibatis/submitted/sqlprovider/SqlProviderTest.java

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.List;
3030
import java.util.Map;
3131

32+
import org.apache.ibatis.annotations.Param;
3233
import org.apache.ibatis.annotations.SelectProvider;
3334
import org.apache.ibatis.builder.BuilderException;
3435
import org.apache.ibatis.builder.annotation.ProviderContext;
@@ -52,6 +53,7 @@ public static void setUp() throws Exception {
5253
Reader reader = Resources
5354
.getResourceAsReader("org/apache/ibatis/submitted/sqlprovider/mybatis-config.xml");
5455
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
56+
sqlSessionFactory.getConfiguration().addMapper(StaticMethodSqlProviderMapper.class);
5557
reader.close();
5658

5759
// populate in-memory database
@@ -472,6 +474,66 @@ public void mapperMultipleParamAndProviderContext() {
472474
}
473475
}
474476

477+
@Test
478+
public void staticMethodNoArgument() {
479+
SqlSession sqlSession = sqlSessionFactory.openSession();
480+
try {
481+
StaticMethodSqlProviderMapper mapper =
482+
sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
483+
assertEquals(1, mapper.noArgument());
484+
} finally {
485+
sqlSession.close();
486+
}
487+
}
488+
489+
@Test
490+
public void staticMethodOneArgument() {
491+
SqlSession sqlSession = sqlSessionFactory.openSession();
492+
try {
493+
StaticMethodSqlProviderMapper mapper =
494+
sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
495+
assertEquals(10, mapper.oneArgument(10));
496+
} finally {
497+
sqlSession.close();
498+
}
499+
}
500+
501+
@Test
502+
public void staticMethodMultipleArgument() {
503+
SqlSession sqlSession = sqlSessionFactory.openSession();
504+
try {
505+
StaticMethodSqlProviderMapper mapper =
506+
sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
507+
assertEquals(2, mapper.multipleArgument(1, 1));
508+
} finally {
509+
sqlSession.close();
510+
}
511+
}
512+
513+
@Test
514+
public void staticMethodOnlyProviderContext() {
515+
SqlSession sqlSession = sqlSessionFactory.openSession();
516+
try {
517+
StaticMethodSqlProviderMapper mapper =
518+
sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
519+
assertEquals("onlyProviderContext", mapper.onlyProviderContext());
520+
} finally {
521+
sqlSession.close();
522+
}
523+
}
524+
525+
@Test
526+
public void staticMethodOneArgumentAndProviderContext() {
527+
SqlSession sqlSession = sqlSessionFactory.openSession();
528+
try {
529+
StaticMethodSqlProviderMapper mapper =
530+
sqlSession.getMapper(StaticMethodSqlProviderMapper.class);
531+
assertEquals("oneArgumentAndProviderContext 100", mapper.oneArgumentAndProviderContext(100));
532+
} finally {
533+
sqlSession.close();
534+
}
535+
}
536+
475537
public interface ErrorMapper {
476538
@SelectProvider(type = ErrorSqlBuilder.class, method = "methodNotFound")
477539
void methodNotFound();
@@ -508,4 +570,48 @@ public String multipleProviderContext(ProviderContext providerContext1, Provider
508570
}
509571
}
510572

573+
public interface StaticMethodSqlProviderMapper {
574+
@SelectProvider(type = SqlProvider.class, method = "noArgument")
575+
int noArgument();
576+
577+
@SelectProvider(type = SqlProvider.class, method = "oneArgument")
578+
int oneArgument(Integer value);
579+
580+
@SelectProvider(type = SqlProvider.class, method = "multipleArgument")
581+
int multipleArgument(@Param("value1") Integer value1, @Param("value2") Integer value2);
582+
583+
@SelectProvider(type = SqlProvider.class, method = "onlyProviderContext")
584+
String onlyProviderContext();
585+
586+
@SelectProvider(type = SqlProvider.class, method = "oneArgumentAndProviderContext")
587+
String oneArgumentAndProviderContext(Integer value);
588+
589+
class SqlProvider {
590+
public static String noArgument() {
591+
return "SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS";
592+
}
593+
594+
public static String oneArgument(Integer value) {
595+
return "SELECT " + value + " FROM INFORMATION_SCHEMA.SYSTEM_USERS";
596+
}
597+
598+
public static String multipleArgument(@Param("value1") Integer value1,
599+
@Param("value2") Integer value2) {
600+
return "SELECT " + (value1 + value2) + " FROM INFORMATION_SCHEMA.SYSTEM_USERS";
601+
}
602+
603+
public static String onlyProviderContext(ProviderContext context) {
604+
return "SELECT '" + context.getMapperMethod().getName()
605+
+ "' FROM INFORMATION_SCHEMA.SYSTEM_USERS";
606+
}
607+
608+
public static String oneArgumentAndProviderContext(Integer value, ProviderContext context) {
609+
return "SELECT '" + context.getMapperMethod().getName() + " " + value
610+
+ "' FROM INFORMATION_SCHEMA.SYSTEM_USERS";
611+
}
612+
613+
}
614+
615+
}
616+
511617
}

0 commit comments

Comments
 (0)