Skip to content

Commit d99b923

Browse files
committed
fixes #549 Allow referencing statement parameters by their actual names (i.e. the names in the method signature). To use this feature, 1) the project must be compiled in Java 8 with '-parameters' option and 2) 'useActualParamName' must be set to true in MyBatis configuration.
1 parent d5fd433 commit d99b923

File tree

5 files changed

+51
-6
lines changed

5 files changed

+51
-6
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ public MethodSignature(Configuration configuration, Class<?> mapperInterface, Me
259259
this.returnsMap = (this.mapKey != null);
260260
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
261261
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
262-
this.paramNameResolver = new ParamNameResolver(method);
262+
this.paramNameResolver = new ParamNameResolver(configuration, method);
263263
}
264264

265265
public Object convertArgsToSqlCommandParam(Object[] args) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public ProviderSqlSource(Configuration config, Object provider) {
5353
+ "'. Sql provider method can not overload.");
5454
}
5555
this.providerMethod = m;
56-
this.providerMethodArgumentNames = new ParamNameResolver(m).getNames();
56+
this.providerMethodArgumentNames = new ParamNameResolver(config, m).getNames();
5757
}
5858
}
5959
}

src/main/java/org/apache/ibatis/builder/xml/XMLConfigBuilder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ private void settingsElement(Properties props) throws Exception {
255255
configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));
256256
configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage")));
257257
configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));
258+
configuration.setUseActualParamName(booleanValueOf(props.getProperty("useActualParamName"), false));
258259
configuration.setLogPrefix(props.getProperty("logPrefix"));
259260
@SuppressWarnings("unchecked")
260261
Class<? extends Log> logImpl = (Class<? extends Log>)resolveClass(props.getProperty("logImpl"));

src/main/java/org/apache/ibatis/reflection/ParamNameResolver.java

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,27 @@
2525

2626
import org.apache.ibatis.annotations.Param;
2727
import org.apache.ibatis.binding.MapperMethod.ParamMap;
28+
import org.apache.ibatis.io.Resources;
29+
import org.apache.ibatis.session.Configuration;
2830
import org.apache.ibatis.session.ResultHandler;
2931
import org.apache.ibatis.session.RowBounds;
3032

3133
public class ParamNameResolver {
3234

3335
private static final String GENERIC_NAME_PREFIX = "param";
36+
private static final String PARAMETER_CLASS = "java.lang.reflect.Parameter";
37+
private static Method GET_NAME = null;
38+
private static Method GET_PARAMS = null;
39+
40+
static {
41+
try {
42+
Class<?> paramClass = Resources.classForName(PARAMETER_CLASS);
43+
GET_NAME = paramClass.getMethod("getName");
44+
GET_PARAMS = Method.class.getMethod("getParameters");
45+
} catch (Exception e) {
46+
// ignore
47+
}
48+
}
3449

3550
/**
3651
* <p>
@@ -49,7 +64,7 @@ public class ParamNameResolver {
4964

5065
private boolean hasParamAnnotation;
5166

52-
public ParamNameResolver(Method method) {
67+
public ParamNameResolver(Configuration config, Method method) {
5368
final Class<?>[] paramTypes = method.getParameterTypes();
5469
final Annotation[][] paramAnnotations = method.getParameterAnnotations();
5570
final SortedMap<Integer, String> map = new TreeMap<Integer, String>();
@@ -68,13 +83,33 @@ public ParamNameResolver(Method method) {
6883
break;
6984
}
7085
}
71-
// When @Param is not specified, use the parameter index as the name
72-
// ("0", "1", ...) gcode issue #71
73-
map.put(paramIndex, name == null ? String.valueOf(map.size()) : name);
86+
if (name == null) {
87+
// @Param was not specified.
88+
if (config.isUseActualParamName()) {
89+
name = getActualParamName(method, paramIndex);
90+
} else {
91+
// use the parameter index as the name ("0", "1", ...)
92+
// gcode issue #71
93+
name = String.valueOf(map.size());
94+
}
95+
}
96+
map.put(paramIndex, name);
7497
}
7598
names = Collections.unmodifiableSortedMap(map);
7699
}
77100

101+
private String getActualParamName(Method method, int paramIndex) {
102+
if (GET_PARAMS == null) {
103+
throw new ReflectionException("Method#getParameters() method does not exist. Relaunch on Java 8 or set false to useActualParamName.");
104+
}
105+
try {
106+
Object[] params = (Object[]) GET_PARAMS.invoke(method);
107+
return (String) GET_NAME.invoke(params[paramIndex]);
108+
} catch (Exception e) {
109+
throw new ReflectionException("Error occurred when invoking Method#getParameters().", e);
110+
}
111+
}
112+
78113
private static boolean isSpecialParameter(Class<?> clazz) {
79114
return RowBounds.class.isAssignableFrom(clazz) || ResultHandler.class.isAssignableFrom(clazz);
80115
}

src/main/java/org/apache/ibatis/session/Configuration.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ public class Configuration {
106106
protected boolean useColumnLabel = true;
107107
protected boolean cacheEnabled = true;
108108
protected boolean callSettersOnNulls = false;
109+
protected boolean useActualParamName = false;
109110

110111
protected String logPrefix;
111112
protected Class <? extends Log> logImpl;
@@ -240,6 +241,14 @@ public void setCallSettersOnNulls(boolean callSettersOnNulls) {
240241
this.callSettersOnNulls = callSettersOnNulls;
241242
}
242243

244+
public boolean isUseActualParamName() {
245+
return useActualParamName;
246+
}
247+
248+
public void setUseActualParamName(boolean useActualParamName) {
249+
this.useActualParamName = useActualParamName;
250+
}
251+
243252
public String getDatabaseId() {
244253
return databaseId;
245254
}

0 commit comments

Comments
 (0)