前几天把Mybatis升级到3.2.2,发现动态SQL的SqlBuilder/SelectBuilder这几个类应经被弃用,取而代之的是一个叫AbstractSQL的抽象类,打开看源码(什么注释都没有。。。);翻了半天官方文档,发现他有个默认的实现SQL类,新的Mybatis可以通过SQL类来构造动态SQL,详情请见官方文档:
http://mybatis.github.io/mybatis-3/statement-builders.html
在参考他的文档的时候,遇到一个奇怪的问题(我参考的是下面这段):
// With conditionals (note the final parameters, required for the anonymous inner class to access them)
public String selectPersonLike(final String id, final String firstName, final String lastName) {
return new SQL() {{
SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FIRST_NAME, P.LAST_NAME");
FROM("PERSON P");
if (id != null) {
WHERE("P.ID like ${id}");
}
if (firstName != null) {
WHERE("P.FIRST_NAME like ${firstName}");
}
if (lastName != null) {
WHERE("P.LAST_NAME like ${lastName}");
}
ORDER_BY("P.LAST_NAME");
}}.toString();
}
在我运行这段代码的时候,会报错:org.apache.ibatis.builder.BuilderException
通过翻看源码org.apache.ibatis.builder.annotation.ProviderSqlSource
终于知道了答案:
public ProviderSqlSource(Configuration config, Object provider) {
String providerMethodName = null;
try {
this.sqlSourceParser = new SqlSourceBuilder(config);
this.providerType = (Class<?>) provider.getClass().getMethod("type").invoke(provider);
providerMethodName = (String) provider.getClass().getMethod("method").invoke(provider);
for (Method m : this.providerType.getMethods()) {
if (providerMethodName.equals(m.getName())) {
if (m.getParameterTypes().length < 2
&& m.getReturnType() == String.class) {
this.providerMethod = m;
this.providerTakesParameterObject = m.getParameterTypes().length == 1;
}
}
}
} catch (Exception e) {
throw new BuilderException("Error creating SqlSource for SqlProvider. Cause: " + e, e);
}
if (this.providerMethod == null) {
throw new BuilderException("Error creating SqlSource for SqlProvider. Method '"
+ providerMethodName + "' not found in SqlProvider '" + this.providerType.getName() + "'.");
}
}
上面代码10-11行指出:方法返回值必须是String,而且参数只能是0或者一个。于是把上面的一窜参数改成:final Map<String, Object> paramMap,测试通过,mybatis会自动把参数封装到Map里面去。
官方文档真是坑爹,希望后面的伙伴们少走弯路。
本文出自ITEYE BLOG,转载请注明出处: