前言
在正式學習mybatis架構源碼之前,需要先弄懂幾個問題?myabtis架構是什麼?為什麼需要mybatis架構?使用mybatis架構帶來的好處是什麼?
回答這幾個問題之前,我們先來看一下,之前在沒有架構的時候,假如使用jdbc的方式進行開發,會怎樣呢?下面來看一段使用jdbc的方式查詢資料庫的代碼吧
public class TestJdbc {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement ps = null;
ResultSet resultSet = null;
String URL = "jdbc:mysql://IP:3306/test?characterEncoding=utf-8";
String USER = "root";
String PASSWORD = "123456";
try{
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(URL, USER, PASSWORD);
String sql = "select * from user where username = ?";
ps = connection.prepareStatement(sql);
ps.setString(1,"zhangfei");
resultSet = ps.executeQuery();
while (resultSet.next()){
System.out.println(resultSet.getInt("id") + ":" +resultSet.getString("address"));
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
resultSet.close();
ps.close();
connection.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
這段代碼,就不用多做解釋了吧,直接運作觀察結果
讓我們來梳理一下在jdbc方式下,這個過程是怎麼完成的呢?
1、建立一個connection對象
可以認為,上面的URL,USERNAME,PASSWORD屬性都是為了建立與資料庫互動的條件,Class.forName指定了要加載的資料庫的連接配接驅動是哪種類型,這裡是mysql類型的資料庫,通過DriverManager.getConnection這一句,可以認為建立了一個與資料庫連接配接的socket通道
2、通過PreparedStatement建立預處理sql語句對象
使用PreparedStatement将外部傳入的sql進行二次處理并包裝成可執行的sql語句
3、執行sql,并擷取傳回結果
将上一步得到的PreparedStatement通過connection傳入sql執行器進行執行,得到結果集resultSet,如果擷取到了執行結果,就封裝在resultSet對象中,就可以解析resultSet
從上面的分析來看,大緻的步驟可分解為3步,建立連接配接對象,建構可執行的PreparedStatement,最後執行查詢擷取結果
其中,最關鍵的步驟想必大家都猜到了,集中在PreparedStatement這個對象的建構與執行中,這也是jdbc完成資料庫的CRUD中最核心的一個對象元件
但是我們發現,在sql語句比較簡單的情況下,通過簡單的參數拼接可以完成CRUD操作,一旦參數比較多,而且入參的方式不再是單一的參數而是對象,集合等,繼續手動拼接,這個二工作量就比較大了
得到結果集之後,還需要我們通過周遊的方式手動去解析,需要對照字段的屬性映射一一解析,當表的字段特别多的時候,這個可就比較折騰人了
綜上所述,使用原生的JDBC的方式進行開發,在使用過程中存在諸多的不友善,導緻開發人員将投入更多的時間和精力在這些瑣碎的sql拼接與結果的解析上,是以需要一種架構,可以幫助開發人員更快的解決這個問題,把精力投入到業務開發中
mybatis解決的問題
了解了jdbc的問題之後,通過mybatis架構的使用,至少可以解決如下幾個使用中的問題
- 與JDBC相比,降低了至少一倍以上的代碼量
- 靈活,不會對應用程式或者資料庫的現有設計強加任何影響,SQL寫在XML裡,從程式代碼中徹底分離,降低耦合度,便于統一管理和優化,可重用
- 提供XML标簽,支援編寫動态SQL語句(XML中使用if, else等)
- 提供映射标簽,支援對象與資料庫的ORM字段關系映射(在XML中配置映射關系,也可以使用注解)
執行流程
從大的方面,将mybatis的執行流程圖總結如下:
1、mybatis配置檔案
-
SqlMapConfig.xml,此檔案作為mybatis的全局配置檔案,配置了mybatis
的運作環境等資訊
-
Mapper.xml,此檔案作為mybatis的sql映射檔案,檔案中配置了操作資料
庫的sql語句。此檔案需要在SqlMapConfig.xml中加載
2、 SqlSessionFactory
通過mybatis環境等配置資訊構造SqlSessionFactory,即會話工廠
3、sqlSession
通過會話工廠建立sqlSession即會話,程式員通過sqlsession會話接口對資料庫
進行增删改查操作
4、 Executor執行器
mybatis底層自定義了Executor執行器接口來具體操作資料庫,Executor接口有
兩個實作,一個是基本執行器(預設)、一個是緩存執行器,sqlsession底層是
通過executor接口操作資料庫的
5、Mapped Statement
它是mybatis一個底層封裝對象,它包裝了mybatis配置資訊及sql映射資訊等。mapper.xml檔案中一個select\insert\update\delete标簽對應一個Mapped Statement對象,select\insert\update\delete标簽的id即是Mappedstatement的id
-
Mapped Statement對sql執行輸入參數進行定義,包括HashMap、基本類型、
pojo,Executor通過Mapped Statement在執行sql前将輸入的java對象映射至sql
中,輸入參數映射就是jdbc程式設計中對preparedStatement設定參數
-
Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本類型、
pojo,Executor通過Mapped Statement在執行sql後将輸出結果映射至java對象
中,輸出結果映射過程相當于jdbc程式設計中對結果的解析處理過程
調用過程流程圖
SqlSession
接收開發人員提供Statement Id 和參數.并傳回操作結果
Executor
MyBatis執行器,是MyBatis 排程的核心,負責SQL語句的生成和查詢緩存的維護
StatementHandler
封裝了JDBC Statement操作,負責對JDBC statement 的操作,如設定參數、将Statement結果集轉換成List集合
ParameterHandler
負責對使用者傳遞的參數轉換成JDBC Statement 所需要的參數
ResultSetHandler
負責将JDBC傳回的ResultSet結果集對象轉換成List類型的集合
TypeHandler
負責java資料類型和jdbc資料類型之間的映射和轉換
MappedStatement
維護了一條<select|update|delete|insert>節點的封裝
SqlSource
負責根據使用者傳遞的parameterObject,動态地生成SQL語句,将資訊封裝到
BoundSql對象中,并傳回BoundSql表示動态生成的SQL語句以及相應的參數資訊
Configuration
MyBatis所有的配置資訊都維持在Configuration對象之中。
通過上面的執行流程圖,以及執行過程中涉及到的各個元件作用,我們可以大緻想象一下mybatis的執行一條sql查詢時的完整鍊路,再具體點我們可以總結為如下這幅圖,
從代碼層面的結構上進行剖析,可以将整個執行過程分為3步
- 解析配置檔案,包括SqlMapConfig.xml以及與業務相關的xml檔案
- 将解析好的配置檔案,如屬性映射,連接配接資料庫資訊等封裝到Configuration對象
- 執行器執行CRUD并傳回結果
當然,從上面的流程圖上看,遠比這3步要複雜,因為mybatis完成并了JDBC本身的功能同時,還進行了更深入的拓展,比如結果集的自動映射,動态sql語句等,而這些過程的執行,需要更多的元件共同配合完成,才有了上述衆多的元件,下一篇我們通過源碼的方式對其中的主要元件進行分析說明
本篇到此結束,最後感謝觀看!