mybatis原理分析

在使用mybatis之前,我們要知道不使用Mybatis的時候我們用JDBC是如何做數據庫相關的操作,進而纔會更加深刻的理解爲什麼我們要使用mybatis這種ORM框架,當然ORM框架還有一個比較有名的開源框架Hibernate,本文我會重點講解爲什麼將JDBC封裝成Mybatis這樣一種持久層框架,在對Mybatis分析完成之後,我會對比兩個ORM框架的異同點.

1.使用JDBC實現數據庫連接

我們先看看我們最熟悉也是最基礎的通過JDBC查詢數據庫數據,一般需要以下七個步驟:
(1)  加載JDBC驅動
(2)  建立並獲取數據庫連接
(3)  創建 JDBC Statements 對象
(4)  設置SQL語句的傳入參數
(5)  執行SQL語句並獲得查詢結果
(6)  對查詢結果進行轉換處理並將處理結果返回
(7)  釋放相關資源(關閉Connection,關閉Statement,關閉ResultSet)
JDBC連接數據庫代碼晚些更新

2.JDBC連接優化與演化到Mybatis

針對於JDBC連接中七個步驟中的有些重複冗餘的部分進行封裝

(1)數據庫連接的創建和釋放

   使用JDBC連接數據庫,每一次進行數據庫操作都需要進行那七個步驟,數據庫連接頻繁的開啓和關閉本身就造成了資源的浪費,影響了系統的性能. 爲了不讓數據庫連接頻繁的創建,我們可以提前創建一定數量的連接放在一個池子裏,然後需要的時候就到池子裏面進行調用,使用完成後再放回這個池子了,這樣就可以解決我們反覆創建連接造成資源浪費的問題,而這個池子一般我們稱呼它叫連接池.連接池種類多種多樣,從DBCP C3p0 Druid(阿里) Bone  HikoariCP(高性能),可以根據自己的需求進行選擇,通過連接池我們就可以反覆利用池子裏已經生成的連接進行數據庫訪問了,減少了頻繁的開啓和關閉數據庫連接的時間,在Java中一個連接池所產生的連接就叫做數據源(DataSouce)

(2)SQL統一存取

我們使用JDBC進行操作數據庫時,SQL語句基本都散落在各個Java類中,這樣有三個不足之處:
第一,可讀性很差,不利於維護以及做性能調優。
第二,改動Java代碼需要重新編譯、打包部署。
第三,不利於取出SQL在數據庫客戶端執行(取出後還得刪掉中間的Java代碼,編寫好的SQL語句寫好後還要Java進行拼湊)。

   既然放在Java代碼有這麼多弊端,每次改動都需要重新編譯成爲class文件,那我們該把這些和SQL相關的代碼放在哪裏呢?熟悉Java Web開發的人一般都會知道xml這個文件格式,像是一般spring struts hibernate等開源框架的配置文件一般都是放在xml中, mybatis採用的也是這種方式,將SQL統一按照key value方式存放在xml配置文件中,需要調用這些SQL的時候就從根據相應的key值去拿到相應的SQL語句

(3).傳入參數映射和動態SQL

   很多情況下,我們都可以通過在SQL語句中設置佔位符來達到使用傳入參數的目的,這種方式本身就有一定侷限性,它是按照一定順序傳入參數的,要與佔位符一一匹配,即使可以使用另一種方式使傳參數不用按照順序。但是,如果我們傳入的參數是不確定的(條件查詢,傳入查詢的參數也是不同的,有時是一個參數、有時可能是三個參數),那麼我們就得在後臺代碼中自己根據請求的傳入參數去拼湊相應的SQL語句,這樣的話還是避免不了在Java代碼裏面寫SQL語句。既然我們已經把SQL語句統一存放在配置文件或者數據庫中了,怎麼做到能夠根據前臺傳入參數的不同,動態生成對應的SQL語句呢?
   我們正常的程序員思維是,通過if和else這類的判斷來進行是最直觀的,類似於JSTL中的<if test=””></if>這樣的標籤,那麼,能不能將這類的標籤引入到SQL語句中呢?假設可以,那麼我們這裏就需要一個專門的SQL解析器來解析這樣的SQL語句,但是,if判斷的變量來自於哪裏呢?傳入的值本身是可變的,那麼我們得爲這個值定義一個不變的變量名稱,而且這個變量名稱必須和對應的值要有對應關係,可以通過這個變量名稱找到對應的值,這個時候我們想到了key-value的Map。解析的時候根據變量名的具體值來判斷。

(4).結果映射

執行SQL語句、獲取執行結果、對執行結果進行轉換處理、釋放相關資源。假如是執行查詢語句,那麼執行SQL語句後,返回的是一個ResultSet結果集,這個時候我們就需要通過Java代碼將ResultSet對象的數據取出來,不然等到釋放資源時就取不到這些結果信息了。我們從前面的優化來看,以及將獲取連接、設置傳入參數、執行SQL語句、釋放資源這些都封裝起來了,只剩下結果處理這塊還沒有進行封裝,如果能封裝起來,每個數據庫操作都不用自己寫那麼一大堆Java代碼,直接調用一個封裝的方法就可以了。一般對執行結果的有哪些處理,有可能將結果不做任何處理就直接返回,也有可能將結果轉換成一個JavaBean對象返回、一個Map返回、一個List返回等等,結果處理可能是多種多樣的。從這裏看,我們必須告訴SQL處理器兩點:第一,需要返回什麼類型的對象;第二,需要返回的對象的數據結構怎麼跟執行的結果映射,這樣才能將具體的值映射到對應的數據結構上。

(5).解決重複SQL語句問題

由於我們將所有SQL語句都放到配置文件中,這個時候會遇到一個SQL重複的問題,幾個功能的SQL語句其實都差不多,有些可能是SELECT後面那段不同、有些可能是WHERE語句不同。有時候表結構改了,那麼我們就需要改多個地方,不利於維護。當我們的代碼程序出現重複代碼時怎麼辦?我們可能會想到AOP,將重複的代碼抽離出來成爲獨立的一個類,然後在各個需要使用的地方進行引用。對於SQL重複的問題,我們也可以採用這種方式,通過將SQL片段模塊化,將重複的SQL片段獨立成一個SQL塊,然後在各個SQL語句引用重複的SQL塊,這樣需要修改時只需要修改一處即可。

待完善…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章