Mybatis 流程解析 之 mapper映射
mybatis mapper映射分析
上篇文章讲到,mybatis是如何解析xml文件,井将其中的xml文件中的各种标签值解析到Configuration对象中的,这篇文章主要讲解为什么我们只需要在框架中定义mapper接口就可以自动实现SQL语句的自动执行,是怎么样进行绑定的?
思路:只有接口和xml文件的情况下,我们是怎样进行SQL绑定的呢,首先想到的是,xml文件中指定的Mapper路径
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.monco.mapper.UserMapper">
<select id="selectByPrimaryKey" resultType="com.monco.entity.User" >
select
id, username, password, real_name
from user
where id = #{id,jdbcType=INTEGER}
</select>
</mapper>
我们猜想是不是因为这个 namespace 标签来帮我们绑定到哪个mapper的呢?然后我们又在mapper文件中定义方法名和xml中的标签id是一致的,那么我们大胆的猜想,xml文件中的这些语句就是通过 namespace + id 进行数据绑定的。
这点在上篇流程解析中已经分析过了,可以参考上篇博客讲解。
mapper接口的绑定与执行
我们都知道mybatis是面向Sqlsession编程,SqlSession 是 MyBaits 对外提供的最关键的核心接口,通过它可以执行数据库读写命令、获取映射器、管理事务等;SqlSession 也意味着客户端与数据库的一次连接,客户端对数据库的访问请求都是由
SqlSession来处理的,SqlSession 由 SqlSessionFactory 创建,每个 SqlSession 都会引用 SqlSessionFactory 中全局唯一单例存在的 configuration 对象。
而SqlSession的创建是由SqlSessionFactory来负责创建的,使用的核心方法是openSessionFromDataSource(ExecutorType, TransactionIsolationLevel, boolean),这里面牵扯到一个很经典的设计模式(策略模式)。
因为我们都是拿到了SqlSession对象,然后根据SqlSession对象来进行数据库的操作。
例如:
@Before
public void init() throws IOException {
//--------------------第一阶段---------------------------
// 1.读取mybatis配置文件创SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 1.读取mybatis配置文件创SqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
inputStream.close();
}
@Test
// 快速入门
public void quickStart() throws IOException {
//--------------------第二阶段---------------------------
// 2.获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 3.获取对应mapper
TUserMapper mapper = sqlSession.getMapper(TUserMapper.class);
//--------------------第三阶段---------------------------
// 4.执行查询语句并返回单条数据
TUser user = mapper.selectByPrimaryKey(1);
System.out.println(user);
System.out.println("----------------------------------");
// 5.执行查询语句并返回多条数据
List<TUser> users = mapper.selectAll();
for (TUser tUser : users) {
System.out.println(tUser);
}
}
拿到SqlSession对象之后,我们会调用getMapper,这个操作,会将接口实例化出来,这里使用的核心技术为 动态代理,牵涉到的核心类包括如下几个:
MapperRegistry:mapper 接口和对应的代理对象工厂的注册中心;
MapperProxyFactory:用于生成 mapper 接口动态代理的实例对象;保证 Mapper 实例对象是局部变量;
MapperProxy:实现了 InvocationHandler 接口,它是增强 mapper 接口的实现;
MapperMethod:封装了 Mapper 接口中对应方法的信息,以及对应的 sql 语句的信息;它是 mapper 接口与映射配置文件中 sql 语句的桥梁; MapperMethod 对象不记录任何状态信息,所以它可以在多个代理对象之间共享;MapperMethod 内几个关键数据结构:SqlCommand : 从 configuration 中获取方法的命名空间.方法名以及 SQL 语句的类型;MethodSignature:封装 mapper 接口方法的相关信息(入参,返回类型);ParamNameResolver: 解析 mapper 接口方法中的入参,将多个参数转成 Map;
具体的方法需要结合代码去看,这个建议去仔细去查看下源码设计,这个模块中核心中的核心便是怎么去关联,又是怎么使用动态代理实现的;动态代理这个知识点我会在后续的知识点中补上。