深度 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的执行逻辑