MyBatis
MyBatis 與 Hibernate 有哪些不同?
Mybatis 相對於 Hibernate 稱為半 ORM 框架,因為 Hibernate 不需要寫 SQL,而 Mybatis 需要寫 SQL。
也因為這點 Mybatis 更加的靈活且輕量。
能針對 SQL進行最佳化,非常靈活地根據條件動態拼接 SQL等,極端情況下效能佔優。
--#{} 和 ${} 的區別
--#{} 完全相當於jdbc中的 ? 佔位符,底層在處理的時候,就是按 ?處理的 (用 PreparedStatement 的 setObject() 方法 )
如果用 #{} 這樣的方式,當引數是簡單型別的時候{} 裡的內容名稱隨意
${} 它就是當作變數值直接拼接
如果用 ${} 的方式,則{} 中間的值,通常寫成 ${value}
為什麼避免使用二級快取 ?
在符合【Cache使用時的注意事項】的要求時,並沒有什麼危害。
其他情況就會有很多危害了。
1)針對一個表的某些操作不在他獨立的namespace下進行。
例如在UserMapper.xml中有大多數針對user表的操作。但是在一個XXXMapper.xml中,還有針對user單表的操作。
這會導致user在兩個名稱空間下的資料不一致。如果在UserMapper.xml中做了重新整理快取的操作,
在XXXMapper.xml中快取仍然有效,如果有針對user的單表查詢,使用快取的結果可能會不正確。
2)更危險的情況是在XXXMapper.xml做了insert,update,delete操作時,會導致UserMapper.xml中的各種操作充滿未知和風險。
有關這樣單表的操作可能不常見。但是你也許想到了一種常見的情況。
多表操作一定不能使用快取 為什麼不能?
首先不管多表操作寫到那個namespace下,都會存在某個表不在這個namespace下的情況。
例如兩個表:role和user_role,如果我想查詢出某個使用者的全部角色role,就一定會涉及到多表的操作。
<select id="selectUserRoles" resultType="UserRoleVO">
select * from user_role a,role b where a.roleid = b.roleid and a.userid = #{userid}
</select>
像上面這個查詢,你會寫到那個xml中呢??
不管是寫到RoleMapper.xml還是UserRoleMapper.xml,或者是一個獨立的XxxMapper.xml中。如果使用了二級快取,都會導致上面這個查詢結果可能不正確。
如果你正好修改了這個使用者的角色,上面這個查詢使用快取的時候結果就是錯的。
這點應該很容易理解。
在我看來,就以MyBatis目前的快取方式來看是無解的。多表操作根本不能快取。
如果你讓他們都使用同一個namespace(透過
Mybatis 中有兩類快取,分別是一級快取和二級快取:
級快取預設開啟,二級快取預設關閉,若開啟可在 SqlSession 之間共享快取資料。級快取預設是會話級快取。即建立一個Salsession物件就是一個會話,一次會話可能會執行多次相同的查詢,這樣快取了之後就能重複利用查詢結果,提高效能,不過 commit、rollback、update、delete 等都會清除快取。不過要注意,不同 SalSession之間的修改不會影響彼此,比如 Salsesion1 讀了資料A,SalSession2將資料改為 B,此時 SalSession1 再讀還是得到 A這就出現了髒資料的問題。
所以,如果是多 SqlSession 或者分散式環境下,就可能有髒資料的情況發生,建議將一級快取級別設定為 statement,_級快取是跨 SqlSession 級別的共享的,同一個 namespace 下的所有操作語句,都影響著同一個 Cache。
開啟二級快取之後,會先從二級快取查詢,找不到再去一級快取查詢,如果一級快取沒有再去資料庫查詢。
在分散式場景下肯定會出現髒資料建議生產上使用 redis 結合 spring cache 進行資料的快取,或者利用 guava、caffeine 進行本地快取。