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;

 

 

 具体的方法需要结合代码去看,这个建议去仔细去查看下源码设计,这个模块中核心中的核心便是怎么去关联,又是怎么使用动态代理实现的;动态代理这个知识点我会在后续的知识点中补上。

 

 

 

 

posted @ 2020-09-22 14:47  一南  阅读(403)  评论(0编辑  收藏  举报