Skip to content

Commit 5fc85a6

Browse files
authored
Merge pull request #1604 from kazuki43zoo/gh-1595
Support to assign single primitive parameter on SQL provider method
2 parents 6e9e4c2 + 9d68282 commit 5fc85a6

File tree

4 files changed

+267
-21
lines changed

4 files changed

+267
-21
lines changed

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

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public class ProviderSqlSource implements SqlSource {
3838
private final Configuration configuration;
3939
private final Class<?> providerType;
4040
private final LanguageDriver languageDriver;
41+
private final Method mapperMethod;
4142
private Method providerMethod;
4243
private String[] providerMethodArgumentNames;
4344
private Class<?>[] providerMethodParameterTypes;
@@ -59,6 +60,7 @@ public ProviderSqlSource(Configuration configuration, Object provider, Class<?>
5960
String providerMethodName;
6061
try {
6162
this.configuration = configuration;
63+
this.mapperMethod = mapperMethod;
6264
Lang lang = mapperMethod == null ? null : mapperMethod.getAnnotation(Lang.class);
6365
this.languageDriver = configuration.getLanguageDriver(lang == null ? null : lang.value());
6466
this.providerType = getProviderType(provider, mapperMethod);
@@ -116,33 +118,45 @@ private SqlSource createSqlSource(Object parameterObject) {
116118
try {
117119
int bindParameterCount = providerMethodParameterTypes.length - (providerContext == null ? 0 : 1);
118120
String sql;
119-
if (providerMethodParameterTypes.length == 0) {
121+
if (parameterObject instanceof Map) {
122+
if (bindParameterCount == 1 && providerMethodParameterTypes[0] == Map.class) {
123+
sql = invokeProviderMethod(extractProviderMethodArguments(parameterObject));
124+
} else {
125+
@SuppressWarnings("unchecked")
126+
Map<String, Object> params = (Map<String, Object>) parameterObject;
127+
sql = invokeProviderMethod(extractProviderMethodArguments(params, providerMethodArgumentNames));
128+
}
129+
} else if (providerMethodParameterTypes.length == 0) {
120130
sql = invokeProviderMethod();
121-
} else if (bindParameterCount == 0) {
122-
sql = invokeProviderMethod(providerContext);
123-
} else if (bindParameterCount == 1
124-
&& (parameterObject == null || providerMethodParameterTypes[providerContextIndex == null || providerContextIndex == 1 ? 0 : 1].isAssignableFrom(parameterObject.getClass()))) {
131+
} else if (providerMethodParameterTypes.length == 1) {
132+
if (providerContext == null) {
133+
sql = invokeProviderMethod(parameterObject);
134+
} else {
135+
sql = invokeProviderMethod(providerContext);
136+
}
137+
} else if (providerMethodParameterTypes.length == 2) {
125138
sql = invokeProviderMethod(extractProviderMethodArguments(parameterObject));
126-
} else if (parameterObject instanceof Map) {
127-
@SuppressWarnings("unchecked")
128-
Map<String, Object> params = (Map<String, Object>) parameterObject;
129-
sql = invokeProviderMethod(extractProviderMethodArguments(params, providerMethodArgumentNames));
130139
} else {
131-
throw new BuilderException("Error invoking SqlProvider method ("
132-
+ providerType.getName() + "." + providerMethod.getName()
133-
+ "). Cannot invoke a method that holds "
134-
+ (bindParameterCount == 1 ? "named argument(@Param)" : "multiple arguments")
135-
+ " using a specifying parameterObject. In this case, please specify a 'java.util.Map' object.");
140+
throw new BuilderException("Cannot invoke SqlProvider method '" + providerMethod
141+
+ "' with specify parameter '" + (parameterObject == null ? null : parameterObject.getClass())
142+
+ "' because SqlProvider method arguments for '" + mapperMethod + "' is an invalid combination.");
136143
}
137144
Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
138145
return languageDriver.createSqlSource(configuration, sql, parameterType);
139146
} catch (BuilderException e) {
140147
throw e;
141148
} catch (Exception e) {
142-
throw new BuilderException("Error invoking SqlProvider method ("
143-
+ providerType.getName() + "." + providerMethod.getName()
144-
+ "). Cause: " + e, e);
149+
throw new BuilderException("Error invoking SqlProvider method '" + providerMethod
150+
+ "' with specify parameter '" + (parameterObject == null ? null : parameterObject.getClass()) + "'. Cause: " + extractRootCause(e), e);
151+
}
152+
}
153+
154+
private Throwable extractRootCause(Exception e) {
155+
Throwable cause = e;
156+
while(cause.getCause() != null) {
157+
cause = e.getCause();
145158
}
159+
return cause;
146160
}
147161

148162
private Object[] extractProviderMethodArguments(Object parameterObject) {

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2009-2018 the original author or authors.
2+
* Copyright 2009-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -41,6 +41,9 @@ public interface Mapper extends BaseMapper<User> {
4141
@SelectProvider(type = OurSqlBuilder.class, method = "buildGetUsersByCriteriaMapQuery")
4242
List<User> getUsersByCriteriaMap(Map<String, Object> criteria);
4343

44+
@SelectProvider(type = OurSqlBuilder.class, method = "buildGetUsersByCriteriaMapWithParamQuery")
45+
List<User> getUsersByCriteriaMapWithParam(Map<String, Object> criteria);
46+
4447
@SelectProvider(type = OurSqlBuilder.class, method = "buildGetUsersByNameQuery")
4548
List<User> getUsersByName(String name, String orderByColumn);
4649

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ public String buildGetUsersByCriteriaMapQuery(final Map<String, Object> criteria
8484
}}.toString();
8585
}
8686

87+
public String buildGetUsersByCriteriaMapWithParamQuery(@Param("id") Integer id, @Param("name") String name) {
88+
return new SQL() {{
89+
SELECT("*");
90+
FROM("users");
91+
if (id != null) {
92+
WHERE("id = #{id}");
93+
}
94+
if (name != null) {
95+
WHERE("name like #{name} || '%'");
96+
}
97+
}}.toString();
98+
}
99+
87100
public String buildGetUsersByNameQuery(final String name, final String orderByColumn) {
88101
return new SQL(){{
89102
SELECT("*");

0 commit comments

Comments
 (0)