Mybatis常見知識點

 

我在個人簡歷上面沒有寫持久層框架,所以這方面在面試的過程問的也比較少,自己總結的也比較粗糙。問的最多的是第二點和第十點


一:工作流程

通過數據源創建一個數據庫連接,將創建的數據庫連接統一放到連接池進行管理,減少每次創建和斷開數據庫連接的開銷。通過Sqlsession去操作數據庫連接。

 


二:#{…} 和${…} 的區別

sql 注入只對 sql 語句的編譯過程有破壞作用,而 PreparedStatement 已經編譯好了,執行階段只是把輸入串作爲數據處理,而不再對 sql 語句進行解析,準備,因此也就避免了 sql 注入問題。

#{}是預編譯處理,$ {}是字符串替換。mybatis在處理#{}時,會將sql中的#{}替換爲?號,調用PreparedStatement的set方法來賦值;mybatis在處理 $ { } 時,就是把 ${ } 替換成變量的值。使用 #{} 可以有效的防止SQL注入,提高系統安全性


三:動態sql

If:經常用作非空判斷和真假判斷;

choose when otherwise:類似 switch case default;

Where:代替sql中的where 1=1,使sql語句正確

trim;用來去除特殊的字符

set:用於更新操作,只需要發送需要更新的字段,不用像Hibernate那樣發送整個pojo

Foreach:針對數組和集合進行循環遍歷(這是實現批量查詢的關鍵)

Select * from table_name where id in

<foreach item=id index=index collection=list open=( separator=, close=)>

#{id}

</foreach>

當傳入的是單參數且參數類型是數組或者list時,collection的值爲array和list

當傳入的多個參數,就需要將參數封裝成map,collection的值是Map的鍵

當傳入的是一個pojo時,collection的值爲該類中需要進行遍歷的數組或集合的屬性名


四:mybatis的關聯查詢

所謂關聯,就是在一個pojo中存在另外一個pojo。這兩個pojo的關係可能是一對一(一個用戶pojo唯一對應一個IdCard的pojo),一對多(一個用戶pojo對應多個訂單Order的pojo),多對多(一個訂單Order的pojo對應多個商品Product的pojo,反之一個商品Producet的pojo也可以對應多個訂單Order的pojo)。

實現方式有兩種:

嵌套查詢,通過select引入另外一個查詢的sql:缺點可能導致較多關聯sql被執行。

嵌套結果:只需要將所有要查詢的字段寫在一個從多表中進行查詢的sql,一次執行。

一對一:association;一對多:collection;多對多:collection,需要藉助一箇中間表。


五:逆向工程注意事項

selectByExample 和selectByExampleWithBLOBs 兩個方法的區別

1>兩個方法的返回的resultMap不同

selectByExample  方法返回:BaseResultMap

selectByExampleWithBLOBs  方法返回:ResultMapWithBLOBs

ResultMapWithBLOBs定義時,繼承了BaseResultMap,並且自己特殊的字段,該字段通常是longvarchar類型,

2>使用場景不同

若檢索大字段時,則需要使用selectByExampleWithBLOBs ,一般情況則使用selectByExample 即可。


六:常見的持久層框架

概念:

jdbc是java連接數據庫操作的原生接口

jpa是java持久化規範,是orm框架的標準,主流orm框架都實現了這個標準

spring data jpa是對jpa規範的再次抽象,底層還是用的實現jpa的hibernate技術

hibernate是一個標準的orm框架,實現了jpa

mybatis也是一個持久化框架,但不完全是一個orm框架,不是依照的jpa規範。

聯繫:

jdbc是比較底層的數據庫操作方式,hibernate和mybatis都是在jdbc的基礎上進行了封裝。

hibernate是將數據庫中的數據表映射爲持久層的java對象,實現對數據表的完整性控制。hibernate的主要思想是面向對象,標準的orm。不建議自己寫sql語句,如果確實有必要推薦hql代替。hibernate是全表映射,只需提供java bean和數據庫表映射關係,

mybatis是將sql語句中的輸入參數parameterMap和輸出結果resultMap映射爲java對象,放棄了對數據表的完整性控制,獲得了更大的靈活性。mybatis擁抱sql,在sql語句方面有更大的靈活性,mybatis不是面向對象,不是標準的orm,更像是sql mapping框架。mybatis是半自動的,需要提供java bean,sql語句和數據庫表的映射關係。


七:dbcp 和 c3p0 的區別

連接池的配置參數:

driverClassName:com.mysql.jdbc.Driver,

Url:jdbc:mysql://localhost:3306/taotao?characterEncoding=utf-8

Hostname:root

Password:root

dbcp 沒有自動的去回收空閒連接的功能 c3p0 有自動回收空閒連接功能 C3P0提供最大空閒時間,DBCP提供最大連接數。前者當連接超過最大空閒連接時間時當前連接就會被斷掉。DBCP當連接數超過最大連接數時,所有連接都會被斷開。所以dbcp會出現丟連接的情況。


八:xml文件和對應dao的關係

通常一個 Xml 映射文件,都會寫一個 Dao 接口與之對應,請問,這個 Dao 接口的工作原理是什麼?Dao 接口裏的方法,參數不同時,方法能重載嗎?

 Dao接口,就是人們常說的 Mapper接口,接口的全限名,就是映射文件中的 namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法內的參數,就是傳遞給sql的參數。Mapper接口是沒有實現類的,當調用接口方法時,接口全限名+方法名拼接字符串作爲 key 值,可唯一定位一個 MappedStatement。Dao 接 口的工作原理是JDK動態代理,Mybatis 運行時會使用JDK 動態代理爲Dao接口生成代理proxy對象,代理對象proxy會攔截接口方法,轉而執行MappedStatement所代表的sql,然後將sql 執行結果返回。Dao接口裏的方法,是不能重載的,因爲是全限名+方法名的保存和尋找策略。


九:常見問題

1:當實體類中的屬性名和表中的字段名不一樣 ,怎麼辦 ?

第1種: 通過在查詢的sql語句中定義字段名的別名,讓字段名的別名和實體類的屬性名一致

 

第2種: 通過來映射字段名和實體類屬性名的一一對應的關係


十:緩存

Mybatis的一級緩存是SqlSession級別。第一次執行select時候會發現sqlsession緩存沒有記錄,會去數據庫查找,然後把結果保存到緩存,第二次同等條件查詢下,就會從緩存中查找到結果。另外爲了避免髒讀,每次執行更新新增刪除時候會清空當前sqlsession緩存。

怎麼判斷某兩次查詢是完全相同的查詢?

mybatis認爲,對於兩次查詢,如果以下條件都完全一樣,那麼就認爲它們是完全相同的兩次查詢。

2.1 傳入的statementId

2.2 查詢時要求的結果集中的結果範圍

2.3. 這次查詢所產生的最終要傳遞給JDBC java.sql.Preparedstatement的Sql語句字符串(boundSql.getSql() )

2.4 傳遞給java.sql.Statement要設置的參數值

二級緩存是namespace級別的。同一個namespace下的搜尋語句共享一個二級緩存。如果開啓了二級緩存,則先從二級緩存中查找,查找不到則委託爲SimpleExecutor查找,而它則會先從一級緩存中查找,查找不到則從數據庫查找。

一、創建一個POJO Bean並序列化

  由於二級緩存的數據不一定都是存儲到內存中,它的存儲介質多種多樣,所以需要給緩存的對象執行序列化

 二、在映射文件中開啓二級緩存

    <!--

        eviction:代表的是緩存回收策略,目前MyBatis提供以下策略。

        (1) LRU,最近最少使用的,一處最長時間不用的對象

        (2) FIFO,先進先出,按對象進入緩存的順序來移除他們

        (3) SOFT,軟引用,移除基於垃圾回收器狀態和軟引用規則的對象

        (4) WEAK,弱引用,更積極的移除基於垃圾收集器狀態和弱引用規則的對象。這裏採用的是LRU, 移除最長時間不用的對形象

        flushInterval:刷新間隔時間,單位爲毫秒,這裏配置的是100秒刷新,如果你不配置它,那麼當 SQL被執行的時候纔會去刷新緩存。

        size:引用數目,一個正整數,代表緩存最多可以存儲多少個對象,不宜設置過大。設置過大會導致內存溢出。 這裏配置的是1024個對象

        readOnly:只讀,意味着緩存數據只能讀取而不能修改,這樣設置的好處是我們可以快速讀取緩存,缺點是我們沒有辦法修改緩存,默認值是false,不允許我們修改

    <cache eviction="LRU" flushInterval="100000" readOnly="true" size="1024"/>

三、在 mybatis-config.xml中開啓二級緩存

    <settings>

        <!--這個配置使全局的映射器(二級緩存)啓用或禁用緩存-->

        <setting name="cacheEnabled" value="true" />

        .....

    </settings>

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