一、引言
上章说了【Pllugin】,这里将展现一下【Mapper】是如何加载、执行的。
二、Mapper加载
1.配置XML
<mappers>
<mapper class="org.apache.ibatis.plugin.Mapper" />
</mappers>
1.2.创建 Mapper.class
public interface Mapper {
@Select("select name from users where id = #{id}")
String selectNameById(Integer id);
}
1.3.构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = null;
try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/plugin/mybatis-config.xml");
SqlSession sqlSession = sqlSessionFactory.openSession()) {
//
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
// Mapper执行
Mapper mapper = sqlSession.getMapper(Mapper.class);
assertEquals("Public user 1", mapper.selectNameById(1));
}
1.4.Mapper的加载
1.5.MapperRegistry
1.5.1.@Select,@Update等注解的解析
org.apache.ibatis.binding.MapperRegistry#addMapper除了将Mapper接口给存储起来,还包含对注解的解析等,具体看【org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#parseStatement】(包含@Select, @Update, @Insert等注解的解析)
1.5.2.Mapper动态代理节点
上诉流程中在加载的时候并未创建对应Mapper的动态代理,org.apache.ibatis.binding.MapperRegistry#getMapper这里面创建的。
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
// 这里才创建的动态代理类
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
二、Mapper执行
上诉一节讲述了MyBatis怎么加载的Mapper.class。接下来看看Mapper.class和Mapper.xml是怎么映射的(@Select等注解的方式也是一致的)。
下列流程如图讲解:1.3.构建SqlSessionFactory Mapper执行的过程。(注:分支实现不过多探讨)
在org.apache.ibatis.binding.MapperMethod.SqlCommand#resolveMappedStatement
中通过org.apache.ibatis.session.Configuration#getMappedStatement(java.lang.String)获取到对应的 MappedStatement,org.apache.ibatis.binding.MapperMethod#execute包含获取参数、拿到返回结果的逻辑。