-
Notifications
You must be signed in to change notification settings - Fork 45.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
更正:Dao 接口里的方法可以重载,但是Mybatis的XML里面的ID不允许重复! #1122
Comments
👍LGTM! |
答案讲了一半,还需要考虑 default method 的情况,下面分情况讨论。 Java 语法层面 JDK Proxy 是支持方法重载的,所以在 情况 1:在 MapperInterface 中的普通 interface method 这种情况下,不同的重载方法由于 从源码角度解读 // file => /org/apache/ibatis/binding/MapperProxy.java:92
private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {
// ......
else {
return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
}
// ......
}
// file => /org/apache/ibatis/binding/MapperMethod.java:224
public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
// ......
MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass,
configuration);
// ......
}
// file => /org/apache/ibatis/binding/MapperMethod.java:254
private MappedStatement resolveMappedStatement(Class<?> mapperInterface, String methodName, Class<?> declaringClass, Configuration configuration) {
// 实际调试过程显示
// "cn.plusman.mybatis.mapper.BlogMapper" + "." + "selectBlog"
String statementId = mapperInterface.getName() + "." + methodName;
// 注意 statementId 里面是不带方法的参数类型的,所以到 MappedStatement 这里是不存在 Java 语法定义上的重载的。
} 情况 2:在 MapperInterface 中的 default mehtod public interface BlogMapper {
/**
* 根据 id 获取博客内容
* @param id
* @return
*/
Blog selectBlog(
int id
);
/**
* default method
* @return
*/
default Blog selectBlog() {
// 可以自定义一些业务逻辑逻辑,也可以理解成 mybatis 的一个拓展点
// some code
// 可以通过调用内部其他方法,返回真实数据
return this.selectBlog(12);
// 单元测试的时候,也可以返回 fake 数据
// return new Blog()
// .setBlogId(12)
// .setContent("hello world");
}
} 源码实现相对简单,跟踪如下 // file => /org/apache/ibatis/binding/MapperProxy.java:92
private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {
// ......
// 判断是否是 default method
if (m.isDefault()) {
try {
if (privateLookupInMethod == null) {
return new DefaultMethodInvoker(getMethodHandleJava8(method));
} else {
return new DefaultMethodInvoker(getMethodHandleJava9(method));
}
} catch (IllegalAccessException | InstantiationException | InvocationTargetException
| NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
// ......
}
// file => /org/apache/ibatis/binding/MapperProxy.java:156
private static class DefaultMethodInvoker implements MapperMethodInvoker {
// 直接触发代理执行,无 MapStatement 绑定逻辑
@Override
public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
return methodHandle.bindTo(proxy).invokeWithArguments(args);
}
} |
本人也是测试过后,发现几个问题,这里其实并不是真正意义上的重载,楼主亲测的可行的重载方法,存在一个很大的问题,就是定义多个有参方法的时候,比如:
结论是:dao中的接口不可可以重载的。用注解的方式就会报Mapped Statements collection already contains value *** |
欢迎提交PR👍 |
说的对,其实这种用法是投机取巧,或者说钻了源码BUG的空子,生产这么用就是挖坑.... |
LGTM |
更正:Dao 接口里的方法可以重载,但是Mybatis的XML里面的ID不允许重复!
此处错误更正:
Dao 接口里的方法可以重载,但是Mybatis的XML里面的ID不允许重复。
Mybatis版本3.3.0,亲测如下:
然后在StuMapper.xml中利用Mybatis的动态sql就可以实现。
能正常运行,并能得到相应的结果,这样就实现了在Dao接口中写重载方法。
总结:
The text was updated successfully, but these errors were encountered: