互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
012:SqlSessionFactoryBuilder源码分析
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();
}
}
}
启动报错:
检查mysql版本8+
引入的包不符合mysql版本,重新引入依赖:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
同时修改配置文件:
启动运行:
4 Mybatis源码分析之getResourceAsReader
Mybatis大体架构流程分析
1.读取resources获取对应的Reader对象。
Reader resourceAsReader = Resources.getResourceAsReader(resource);
通过Resources类对InputStreamReader类做一层包装,getResourceAsReader功能是读取mybatis配置文件获得InputStreamReader。
5 Mybatis源码分析之SqlSessionFactoryBuilder
2.使用SqlSessionFactoryBuilder获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
具体分析:
2.1 进入到SqlSessionFactoryBuilder的build有参数构造函数,传递reader;
2.2 获得XMLConfigBuilder,new出一个成员变量configuration;
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
问:为什么XMLConfigBuilder只能被使用一次?Each XMLConfigBuilder can only be used once.
答:因为配置文件 Configuration是一个全局的属性,所以只能被解析一次。
2.3 执行parse方法,开始解析相关配置信息;具体在parseConfiguration方法里面处理配置文件信息;
var5 = this.build(parser.parse());
6 Mybatis源码分析之XMLConfigBuilder
2.4 environmentsElement方法将环境相关配置信息装载到configuration中;
2.5 进入mapperElement方法,得到一个XMLMapperBuilder,parse()方法可以解析mybatisMapper文件;
2.6 装载loadedResources到configuration中;loadedResources 存放的是mybatis映射的文件路由地址,使用set集合存放。
protected final Set<String> loadedResources = new HashSet<String>();
2.7 绑定mapper接口和配置中namespace的位置对应关系;
注意:mapper文件配置的namespace一定要和接口对应 否则会查找失败!
mapperRegistry作用存放dao层mapper接口,底层使用map集合存放。
XMLConfigBuilder的作用:解析mybatis配置文件,装配到configuration中
7 MyBatis源码分析之configuration
2.8 返回configuration变量
2.9 使用configuration获取默认的DefaultSqlSessionFactory
总结:
1.获取本地InputStreamReader对象(mybatis配置文件);
2.调用SqlSessionFactoryBuilder;
3.使用XMLConfigBuilder解析mybatis配置文件,装配到Configuration中;
4.将配置文件中的Mapper添加到Configuration mapperRegistry实现注册;
备注:mapperRegistry存放当前所有的mapper文件。
5.使用Configuration获取默认的DefaultSqlSessionFactory.
推荐阅读
-
互联网架构-Java8集合框架源码分析-041:纯手写Jdk7HashMap集合框架
-
互联网架构-Java8集合框架源码分析-040:LinkedList集合源码深度解析
-
SpringBoot 03——深入SpringBoot底层源码架构分析引导类注解的具体实现
-
互联网架构-Mybatis深入源码分析-014:SQLSession一级缓存原理分析
-
互联网架构-Mybatis深入源码分析-013:Mapper与接口绑定原理源码分析
-
互联网架构-Mybatis深入源码分析-015:SqlSessionFactory二级缓存原理分析
-
互联网架构-Mybatis深入源码分析-012:SqlSessionFactoryBuilder源码分析
-
深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)
-
深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)
-
SpringBoot 03——深入SpringBoot底层源码架构分析引导类注解的具体实现