深度 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的執行邏輯
&n