欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析

程序员文章站 2022-06-15 11:33:42
...

1 源码分析需要那些基础内容

如果想看懂源码需要那些基础?
Java反射机制使用、设计模式、面向对象思想(封装、继承、多态)、断点调试、画图…

课程内容:
1.MyBatis环境搭建与MyBatis基础内容回顾
2.MyBatis大体执行流程源码分析
3.SqlSessionFactoryBuilder源码分析
4.XMLConfigBuilder源码分析
5.Configuration源码分析

2 快速搭建MyBatis入门环境

为什么要使用Mybatis
MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录

搭建MyBatis入门环境
1、引入maven jar包
2、定义mybatis_config文件
3、mapper层编写sql与接口关联
4、使用mybatis Api操作数据库

Maven依赖信息

<dependencies>
    <!-- mybatis核心包 -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.3.0</version>
    </dependency>
    <!-- mysql驱动包 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.29</version>
    </dependency>
    <!-- junit测试包 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.10</version>
    </dependency>
</dependencies>

创建mybatis配置文件 configuration

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 环境配置 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <!-- 数据库连接相关配置 ,这里动态获取config.properties文件中的内容-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!-- mapping文件路径配置 -->
    <mappers>
        <mapper resource="mappers/UserMapper.xml"/>
    </mappers>

</configuration>

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,namespace的值习惯上设置成包名+sql映射文件名,这样就能够保证namespace的值是唯一的
例如namespace="com.mayikt.mapper.UserMapper"就是com.mayikt.mapper(包名)+userMapper(userMapper.xml文件去除后缀)
 -->
<mapper namespace="com.mayikt.mapper.UserMapper">
    <!-- 在select标签中编写查询的SQL语句, 设置select标签的id属性为getUser,id属性值必须是唯一的,不能够重复
    使用parameterType属性指明查询时使用的参数类型,resultType属性指明查询返回的结果集类型
    resultType="com.mayikt.entity.User"就表示将查询结果封装成一个User类的对象返回
    User类就是users表所对应的实体类
    -->
    <!--
        根据id查询得到一个user对象
     -->
    <select id="getUser" parameterType="int"
            resultType="com.mayikt.entity.UserEntity">
        select * from user where id=#{id}
    </select>
</mapper>

Dao层和实体类

package com.mayikt.mapper;

import com.mayikt.entity.UserEntity;

public interface UserMapper {
    public UserEntity getUser(int id);
}
package com.mayikt.entity;

import lombok.Data;

@Data
public class UserEntity {
    private Long id;
    private String name;
    private Integer age;
    
}

3 MyBatis获取SqlSessionFactory

数据表结构

CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `user` VALUES ('1', 'zhangsan', '18');
INSERT INTO `user` VALUES ('2', 'lisi', '19');

运行MyBatis代码

public class TestMyBatis {
    public static void main(String[] args) {

        try {
            // 1.定义mybatis文件
            String resource = "mybatis_config.xml";
            // 2.获取InputStreamReader
            Reader resourceAsReader = Resources.getResourceAsReader(resource);
            // 3.获取SqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
            // 4.获取Session
            SqlSession sqlSession = sqlSessionFactory.openSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            UserEntity user = mapper.getUser(1);
            System.out.println(user.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

启动报错:
互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
检查mysql版本8+互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
引入的包不符合mysql版本,重新引入依赖:

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.17</version>
</dependency>

同时修改配置文件:
互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
启动运行:
互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析

4 Mybatis源码分析之getResourceAsReader

Mybatis大体架构流程分析

1.读取resources获取对应的Reader对象。

Reader resourceAsReader = Resources.getResourceAsReader(resource);

互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
通过Resources类对InputStreamReader类做一层包装,getResourceAsReader功能是读取mybatis配置文件获得InputStreamReader。

5 Mybatis源码分析之SqlSessionFactoryBuilder

2.使用SqlSessionFactoryBuilder获取SqlSessionFactory

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);

具体分析:
2.1 进入到SqlSessionFactoryBuilder的build有参数构造函数,传递reader;
互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
2.2 获得XMLConfigBuilder,new出一个成员变量configuration;

XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);

互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
问:为什么XMLConfigBuilder只能被使用一次?Each XMLConfigBuilder can only be used once.
答:因为配置文件 Configuration是一个全局的属性,所以只能被解析一次。

2.3 执行parse方法,开始解析相关配置信息;具体在parseConfiguration方法里面处理配置文件信息;

var5 = this.build(parser.parse());

互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析

6 Mybatis源码分析之XMLConfigBuilder

2.4 environmentsElement方法将环境相关配置信息装载到configuration中;互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
2.5 进入mapperElement方法,得到一个XMLMapperBuilder,parse()方法可以解析mybatisMapper文件;互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
2.6 装载loadedResources到configuration中;loadedResources 存放的是mybatis映射的文件路由地址,使用set集合存放。

protected final Set<String> loadedResources = new HashSet<String>();

互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
2.7 绑定mapper接口和配置中namespace的位置对应关系;
注意:mapper文件配置的namespace一定要和接口对应 否则会查找失败!
mapperRegistry作用存放dao层mapper接口,底层使用map集合存放。
互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
XMLConfigBuilder的作用:解析mybatis配置文件,装配到configuration中

7 MyBatis源码分析之configuration

2.8 返回configuration变量
互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
2.9 使用configuration获取默认的DefaultSqlSessionFactory
互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
总结:
1.获取本地InputStreamReader对象(mybatis配置文件);
2.调用SqlSessionFactoryBuilder;
3.使用XMLConfigBuilder解析mybatis配置文件,装配到Configuration中;
4.将配置文件中的Mapper添加到Configuration mapperRegistry实现注册;
备注:mapperRegistry存放当前所有的mapper文件。
5.使用Configuration获取默认的DefaultSqlSessionFactory.