一、BUG还原
在编写mybatis通用增删改查方法时,使用的是Provider动态拼接sql.启动项目报错
Caused by: org.apache.ibatis.builder.BuilderException:
Error creating SqlSource for SqlProvider. Method 'deleteById' not found in SqlProvider 'com.*'.
二、分析原因
根据报错信息查看,为ProviderSqlSource类的init初始化方法。
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);
Method[] arr$ = this.providerType.getMethods();
int len$ = arr$.length;
for(int i$ = 0; i$ < len$; ++i$) {
Method m = arr$[i$];
//providerMethod在赋值时的条件是 :
//1、当前方法与类中所有方法的hash值进行对比
//2、方法的参数必须少于2个
//3、方法的返回值必须为字符串
if (providerMethodName.equals(m.getName()) && m.getParameterTypes().length < 2 && m.getReturnType() == String.class) {
this.providerMethod = m;
this.providerTakesParameterObject = m.getParameterTypes().length == 1;
}
}
} catch (Exception var8) {
throw new BuilderException("Error creating SqlSource for SqlProvider. Cause: " + var8, var8);
}
//providerMethod这个变量为空时,抛出异常
if (this.providerMethod == null) {
throw new BuilderException("Error creating SqlSource for SqlProvider. Method '" + providerMethodName + "' not found in SqlProvider '" + this.providerType.getName() + "'.");
}
}
看到这个,就明白了。看我的代码,传入两个参数。这个就是原因所在,我考虑架构师应该是为了避免重写问题,所以在这过滤重载问题,而这个设计的。
public String deleteById(String id,String tableName){
SQL sql = new SQL();
sql.UPDATE(tableName);
sql.SET("dr = 1");
sql.WHERE( "id ="+id );
return sql.toString();
}
三、其他
刚开始搜索时,给出的答案是MyProvider动态拼接的方法必须是public修饰,因为源码中没有暴力破解,所以私有方法无法反射导致,小伙伴们也请注意下