Mybatis中Mapper接口的工作原理
对应的关系如下:
"namespace"
的值。MappedStatement
的 "id" 值。SQL
的参数。Mapper
接口是没有实现类的,当调用接口方法时,接口全限名 + 方法名拼接字符串作为 key 值,可唯一定位一个对应的 MappedStatement
。
例如,如下接口全限名 + 方法名拼接字符串作为key
com.coderjia.content.app.dao.IActivityDao#addSignInLog
可以定位到namespace
为
com.coderjia.content.app.dao.IActivityDao
中id为"addSignInLog"
的MappedStatement
。
Mybatis 中,每一个 <insert/>
、<delete/>
、<update/>
、<select/>
标签,都会被解析为一个 MappedStatement
对象,和Mapper里的接口一一对应。
再看看重载
重载(Overload
)是一个类中多态性的一种表现。如果在一个类中定义了多个同名的方法,它们参数列表不同,则称为方法的重载(Overload
)。
而Mapper
接口在定位MappedStatement
时是不使用参数来定位的,所以重载的接口方法是无法唯一定位到其匹配的MappedStatement
的。
在 MyBatis 中,Mapper 接口的方法不能重载的原因主要是因为 MyBatis 是通过 Mapper 接口方法名来映射 SQL 语句的。如果允许方法重载,会导致方法名相同但参数不同的情况,这样 MyBati就无法准确地根据方法名来映射正确的 SQL 语句。
public interface UserMapper {
User getUserById(int id);
User getUserByName(String name);
}
假设允许方法重载,那么在调用 getUser
方法时,无法确定是要执行哪个 SQL 语句,因为方法名相同,参数不同。为了避免这种混淆,MyBatis 不支持在 Mapper 接口中定义方法重载。
解决这个问题的一种方法是使用不同的方法名来表示不同的查询,如:
public interface UserMapper {
User getUserById(int id);
User getUserByName(String name);
}
需要注意的是,虽然在 Mapper 接口中不能直接定义方法重载,但在 XML 映射文件中是可以定义多个不同参数的 SQL 语句并通过不同的 id 进行区分的。这样就能够实现不同参数的查询操作。
从底层简单说一下:
MyBatis的底层工作原理涉及到了Java的反射机制和动态代理技术,而方法重载涉及到方法的参数列表,这会导致在底层实现时产生歧义,因此MyBatis禁止了Mapper接口方法的重载。
本文系作者在时代Java发表,未经许可,不得转载。
如有侵权,请联系nowjava@qq.com删除。