深度 Mybatis 3 源码分析(一)SqlSessionFactoryBuilder源码分析

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

Mybatis环境快速入门

Maven依赖信息

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>sourceanalysis</artifactId>
        <groupId>com.brian</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>


    <artifactId>mybatis3</artifactId>
    <groupId>com.brian</groupId>
    <version>0.0.1-SNAPSHOT</version>
    <description>源码分析 - mybatis3源码分析</description>


    <dependencies>
        <!--mysql数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>

        <!-- mybatis ORM框架 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.1</version>
        </dependency>
    </dependencies>

</project>

创建mybatis配置文件 mybatis.xml

<?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="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <!-- 数据库连接相关配置 ,这里动态获取config.properties文件中的内容-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:14110/brian?useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!-- mapping文件路径配置 -->
    <mappers>
        <mapper resource="mapper/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="mapper.UserMapper">
    <select id="getUser" parameterType="int"
            resultType="entity.User">
        select * from user where id=#{id}
    </select>
</mapper>

运行MyBatis代码

import mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.Reader;

/**
 * @program: architect
 * @author: Brian Huang
 * @create: 2019-06-04 22
 **/
public class MybatisApp {

    public static void main(String[] args) {
        try {
            //1.定义配置文件
            String resource = "mybatis.xml";
            //2.获取InputStreamReader IO流
            Reader reader = Resources.getResourceAsReader(resource);
            //3.获取SqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
            //4.获取Session
            SqlSession session = sqlSessionFactory.openSession();
            //5.执行mapper接口方法
            UserMapper mapper = session.getMapper(UserMapper.class);
            System.out.println("--result--: " + mapper.getUser(1).toString());

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

数据表结构

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
  `password` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码,加密存储',
  `phone` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '注册手机号',
  `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '注册邮箱',
  `created` datetime(0) NOT NULL,
  `updated` datetime(0) NOT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `username`(`username`) USING BTREE,
  UNIQUE INDEX `phone`(`phone`) USING BTREE,
  UNIQUE INDEX `email`(`email`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 36 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

Mybatis大体架构流程分析

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

Reader reader = Resources.getResourceAsReader(resources);

2. 使用SqlSessionFactoryBuilder获取SqlSessionFactory

SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);

源码分析:

2.1.进入到build 传递reader有参数构造函数

最终执行

2.2. SqlSessionFactoryBuilder使用XMLConfigBuilder解析配置文件,封装成Configuration对象。

 

注意:parsed = false,避免maybatis.xml被加载多次,因为我们的configuration是全局的所以只能被解析一次

 2.3 执行environmentsElement()  方法

 

此处for循环是environment可能回配置多个运行环境如dev,test,prod等

 2.4 执行mapperElement()方法 解析mybatis.xml里面的<mappers>节点

 

这里的Mapper有两种扫描的方式 package和resource,根据我上面的mybatis.xml配置文件,这里会走第一个判断

2.5 执行XMLMapperBuilder的parse()方法,解析UserMapper.xml

2.5.1 isResourceLoaded() 判断避免mapper被重复解析

 

2.5.2 configurationElement()执行具体的解析UserMapper.xml逻辑

2.5.3 addLoadedResource()方法Mapper路径放入到loadedResoures中

 

 2.5.4 执行bingMapperForNamesapce() 将UserMapper.XML和UserMapper.java 进行映射

 

总环下流程图 (PS 图画的不是太好看) 红色框为SqlSessionFactoryBuilder的执行逻辑

 

posted @ 2019-06-06 00:04  Brian_Huang  阅读(664)  评论(0编辑  收藏  举报