<code>《“愛讀書”--給你講技術》,我來看書,你來進步,讓我們開始吧!/<code>
本書簡介
書名為《Spring+MyBatis企業應用實戰》,是本人在學習JavaEE框架時候的一本基礎書籍,本書對於SpringMVC和MyBatis框架及相關基礎知識講述的比較清晰,適合需要詳細學習Java框架的讀者。
本文內容為本書第八章--第十一章,記錄和總結了所有MyBatis的知識
MyBatis開發步驟
1.導入MyBatis依賴的Jar包
2.創建持久化類
3.配置持久化類映射,即配置Mapper
4.配置MyBatis配置文件,即mybatis-config.xml
5.在程序中調用對應方法實現持久化操作
核心對象SqlSessionFactory和SqlSession
1.SqlSessionFactory
SqlSessionFactory是MyBatis的關鍵對象,它是單個數據庫映射關係經過編譯後的內存鏡像。SqlSessionFactory的實例可以通過SqlSessionFactoryBuilder對象來獲得,SqlSessionFactory是線程安全的, SqlSessionFactory一旦被創建,在應用執行期間都存在,不需要重複創。
SqlSessionFactory是創建SqlSession的工廠,創建方法如下:
<code>SqlSession openSession():創建SqlSession對象/<code>
2.SqlSession
SqlSession是執行持久化操作的對象,類似於JDBC中的Connection。它是應用程序與持久存儲層之間執行交互操作的一個單線程對象。
SqlSession對象包含以數據庫為背景的所有執行SQL操作的方法,它的底層封裝了JDBC連接,可以用SqlSession實例來直接執行已映射的 SQL語句。
每個線程都應該有它自己的SqlSession實例,是線程不安全的。使用完SqlSession之後必須要關閉它。
SqlSession常用方法如下:
<code>int insert(String statement):插入方法,參數是Mapper中元素的id,返回執行的行數 int insert(String statement, Object parameter):插入方法,parameter是插入所需的參數 int update(String statement):更新方法,參數是Mapper中元素的id,返回執行的行數 int update(String statement, Object parameter):更新方法,parameter是更新所需的參數 int delete(String statement):刪除方法,參數是Mapper中元素的id,返回執行的行數 int delete(String statement, object parameter):刪除方法,parameter是刪除所需的參數 T selectOne(String statement):查詢方法,參數是Mapper中/<code>
MyBatis配置文件
1.MyBatis SqlSessionFactory初始化過程
(1)調用SqlSessionFactoryBuilder對象的build(inputStream)方法
(2)SqlSessionFactoryBuilder會根據輸入流inputStream等信息創建XMLConfigBuilder對象
(3)SqlSessionFactoryBuilder調用XMLConfigBuilder對象的parse()方法
(4)XMLConfigBuilder對象解析XML配置文件返回Configuration對象
(5)SqlSessionFactoryBuilder根據Configuration對象創建一個DefaultSessionFactory對象
(6)SqlSessionFactoryBuilder返回DefaultSessionFactory對象給客戶端使用
2.MyBatis配置文件屬性
- 頂層configuration 配置
- properties 屬性
- settings 設置
- typeAliases 類型命名
- typeHandlers 類型處理器
- objectFactory 對象工廠
- plugins 插件
- environments 環境
- environment 環境變量
- transactionManager 事務管理器
- dataSource 數據源
- databaseIdProvider 數據庫廠商標識
- mappers 映射器
(1)properties
在classpath中增加db.properties屬性文件
配置如下:
<code>/<code>
調用屬性文件的值:
<code> /<code>
(2)setting
設置MyBatis運行時參數
配置如下:
<code> /<code>
參數包含如下:
(3)typeAliases
類型別名是為Java類型設置的一個短的名字。它只和XML配置有關,僅用來減少類完全限定名的冗餘。
<code> /<code>
MyBatis內建了java類型的別名如下:
(4)typeHandlers
類型處理器將獲取的值以合適的方式轉換成Java類型
(5)objectFactory
MyBatis每次創建新實例時,都會使用一個對象工廠。如何想覆蓋對象工廠的默認行為,可以通過創建自己的對象工廠來實現,繼承並重寫DefaultObjectFactory。配置如下:
<code> /<code>
(6)environments
environments配置就是數據源的配置。每個SqlSessionFactory實例只能選擇一個環境,即每個數據庫對應一個SqlSessionFactory實例。
配置方式如下:
(1)要配置默認的環境id
(2)每個environment要定義環境id
(3)需要配置事務管理器,包括JDBC和MANAGED
(4)需要配置數據源,包括POOLED、UNPOOLED、JNDI
(7)mapper
mapper映射器告訴MapBatis去哪裡找映射文件。可以使用相對於類路徑的引用、全限定資源定位符或類名包名等。配置如下:
<code> /<code>
MyBatis日誌信息配置
配置日誌實現方式
<code> /<code>
配置mapper接口所對應的日誌級別
(1)採用properties文件配置
<code>//設置某個方法的日誌級別 log4j.logger.org.fkit.mapper.UserMapper.selectUser=DEBUG //設置包的日誌級別 log4j.logger.org.fkit.mapper=DEBUG/<code>
(2)採用xml文件配置
<code>//設置某個方法的日誌級別 //設置包的日誌級別 /<code>
深入Mapper映射文件
SQL映射文件常用元素:
- select:映射查詢語句
- insert:映射插入語句
- update:映射更新語句
- delete:映射刪除語句
- sql:可被其他語句引用的可重用語句塊
- cache:給定命名空間的緩存配置
- cache-ref:其他命名空間緩存配置引用
- resultMap:用來描述如何從數據庫結果集加載對象
1.select
select元素用來映射查詢語句
參數符號#{id},是指創建一個預處理語句參數,就是JDBC SQL語句中的?
select元素屬性如下:
- id:在命名空間中唯一的標識符,可以被用來引用這條語句
- parameterType:將會傳入這條語句的參數類的完全限定名或別名。這個屬性是可選的,因為MyBatis可以通過TypeHandler推斷出具體傳入語句的參數,默認值為unset
- resultType:返回值的類型的類的完全限定名或別名。注意如果是集合情形,那應該是集合可以包含的類型,而不能是集合本身。返回時可以使用resultType或resultMap
- resultMap:外部resultMap的命名引用
- flushCache:如果設置為 true,則任何時候只要語句被調用,都會導致本地緩存和二級緩存都被清空,默認值為false
- useCache:如果設置為 true,將會導致本條語句的結果被二級緩存,在select元素當中默認值為 true
- timeout:這個設置是在拋出異常之前,驅動程序等待數據庫返回請求結果的秒數。默認值為 unset
- fetchSize:其嘗試使每次批量返回的結果行數和這個設置值相等。默認值為 unset
- statementType:值為STATEMENT、PREPARED或CALLABLE。這會讓MyBatis分別使用 JDBC 中的Statement、PreparedStatement或CallableStatement,默認值為PREPARED
- resultSetType:結果集的類型,值為FORWARD_ONLY、SCROLL_SENSITIVE或SCROLL_INSENSITIVE,默認值為unset
- databaseId:如果配置了databaseIdProvider,MyBatis會加載所有的不帶databaseId或匹配當前 databaseId 的語句;如果帶或者不帶的語句都有,則不帶的會被忽略
- resultOrdered:這個設置僅針對嵌套結果select語句適用:如果為true,就是假設包含了嵌套結果集或分組,這樣的話當返回一個主結果行的時候,就不會發生對前面結果集引用的情況。這就使得在獲取嵌套的結果集時不至於導致內存不夠用。默認值為false
- resultSets:這個設置僅對多結果集的情況適用,它將列出語句執行後返回的結果集並給每個結果集起一個名稱,名稱是逗號分隔的
2.insert、update和delete
常用屬性舉例如下:
insert、update 和 delete元素的屬性大多和select的一致,它們特有的屬性如下:
- useGeneratedKeys:(僅對 insert 和 update 有用)這會令MyBatis使用JDBC的getGeneratedKeys方法來獲取由數據庫內部生成的主鍵,默認值為false
- keyProperty:(僅對 insert 和 update 有用)唯一標記一個屬性,MyBatis會通過getGeneratedKeys的返回值或者通過insert語句的selectKey子元素設置它的鍵值,默認為unset
- keyColumn:(僅對insert和update有用)通過生成的鍵值設置表中的列名,這個設置僅對某些數據庫(像PostgreSQL)是必須的,當主鍵列不是表中的第一列時需要設置
insert插入主鍵的方式
(1)如果數據庫支持主鍵生成方式(如:MySQL和SQL Server)
(2)如果數據庫採用其他方式生成主鍵(如:Oracle)
3.sql
sql元素被用來定義可重用的SQL代碼段,可以包含在其他語句中,
定義SQL
使用SQL
4.參數(Parameters)
簡單數據類型
複雜對象
5.ResultMaps
resultMap元素作用是講結果集中取出的數據轉換成開發者所需的對象
(1)單表映射
舉例如下:
resultType表示將返回的結果集轉換成一個Map集合
當然也可以將結果集轉換成持久化對象
默認情況下,MtBatis會將查詢到的數據列和需要返回的對象的屬性逐一進行匹配賦值,但如果查詢到的數據列和需要返回的對象屬性不一致,就無法自動賦值了。這時需要使用resultMap處理。
如下圖:
上圖使用resultMap將持久化對象屬性和表的字段進行匹配
resultMap常用屬性如下:
- id:唯一標識符
- type:實際返回的類型
- 子元素指定數據庫表的主鍵,column為列名,property為對象屬性
- 子元素指定數據庫表的普通列
(2)多表關聯映射(1對1)
多表查詢的情況,當查詢某個對象同時關聯查詢了另一個對象時使用
<code> /<code>
說明如下:
- 查詢所有的學生數據,此時返回的不是簡單的Student對象,因為Student對象中還包含了Clazz對象,所以使用resultMap去映射返回類型
- resultMap中查詢的班級id列clazz_id則使用了關聯映射,元素屬性如下:
<code>column:數據庫表列名 property:返回的對象類型 javaType:property屬性對應的java類型 select:執行一條查詢語句,將查詢到的數據封裝到property所代表的對象中/<code>
(3)多表關聯映射(1對多)
多表查詢的情況,當查詢某個對象同時關聯查詢了List對象時使用
<code> /<code>
說明如下:
- 查詢所有的班級數據,此時返回的不是簡單的Clazz對象,因為Clazz對象中還包含了學生的集合對象,所以使用resultMap去映射返回類型
- 查詢班級所有學生時使用了集合映射,屬性如下:
<code>property:返回的集合類型的屬性名 javaType:property屬性對應的java類型 ofType:集合中的類型 column:使用當前表的哪個列名作為查詢集合的條件 select:執行一條查詢語句,將查詢到的數據封裝到property所代表的對象中 fetchType:設置集合屬性加載的方式,包括eager和lazy,eager立即加載,lazy延遲加載/<code>
一般來說1對多關聯大多被設置成lazy,全局設置方式如下:
<code>//mybatis-config.xml文件 /<code>
(4)多表關聯映射(多對多)
多對多關聯,單獨看每個對象的映射,其實就是1對1和1對多的組合。所以只需組合使用和元素即可。
MyBatis調用存儲過程
1.操作數據的存儲過程
插入數據
存儲過程如下:
配置如下:
(1)調用存儲過程時,需要把statementType屬性的值設置為CALLABLE
(2)call是用來調用存儲過程的關鍵字,需要注意的是,OUT模式的參數必須指定jdbcType,這是因為在IN模式下,MyBatis提供了默認的jdbcType,而在OUT模式下沒有提供
修改數據
存儲過程如下:
配置如下:
刪除數據
存儲過程如下:
配置如下:
2.查詢數據的存儲過程
存儲過程如下:
配置如下:
調用名為select_user的存儲過程查詢所有User數據並返回List,查詢到的每一條數據會被封裝到User對象中
3.根據條件查詢的存儲過程
存儲過程如下:
配置如下:
MyBatis事務管理
1.Transaction接口
MyBatis事務核心是
org.apache.ibatis.transaction.Transaction接口。Transaction接口有兩個實現類:
- JdbcTransaction
- ManagedTransaction
同時MyBatis還設計了
org.apache.ibatis.transaction.TransactionFactory接口,實現類:
- JdbcTransactionFactory
- ManagedTransactionFactory
以上類可用來獲取事務的實例對象
MyBatis管理事務的兩種方式:
(1)使用JDBC的事務管理機制。利用java.sql.Connection對象完成對事務的提交(commit)、回滾(rollback)和關閉(close)等操作
(2)使用MANAGED的事務管理機制。這種機制MyBatis自身不會去實現事務管理,而是讓容器如WebLogic、JBoss等來實現對事務的管理
2.事務的配置創建和使用
(1)事務的配置
元素的type決定我們用什麼類型的事務管理機制
(2)事務工廠的創建
MyBatis的事務創建是由TransactionFactory事務工廠來完成的。如果type="JDBC",則MyBatis會創建一個JdbcTransactionFactory的實例;如果type="MANAGED",則MyBatis 會創建一個MangedTransactionFactory的實例
(3)事務工廠TransactionFactory
JdbcTransactionFactory會創建JDBC類型的Transaction,即JdbcTransaction。類似地,ManagedTransactionFactory也會創建ManagedTransaction
(4)JdbcTransaction
JdbcTransaction可直接使用JDBC的提交和回滾事務管理機制。它依賴於從dataSource中取得的連接 connection來管理transaction的作用域。如果將autocommit設置為on,開啟狀態的話,則它會忽略commit和rollback。
MyBatis緩存機制
1.一級緩存(SqlSession級別)
在操作數據庫時需要構造SqlSession對象,在SqlSession對象中有一個HashMap用於存儲緩存數據。不同的SqlSession之間的緩存數據區域是互相不影響的。
如果SqlSession執行了DML操作(insert、update、delete),並提交到數據庫,MyBatis則會
清空SqlSession中的一級緩存
Mybatis默認開啟一級緩存,不需要進行任何配置
MyBatis的緩存機制是基於id進行緩存的,MyBatis使用HashMap緩存數據時,是使用對象的id作為key,對象作為value
2.二級緩存(mapper級別)
使用二級緩存時,多個SqlSession使用同一個mapper的SQL語句去操作數據庫,得到的數據會存在二級緩存區域,它同樣是使用HashMap進行數據存儲的。相比一級緩存 SqlSession,二級緩存的範圍更大,多個SqlSession可以共享二級緩存中的數據,二級緩存是跨SqlSession的。
MyBatis默認沒有開啟二級緩存,需要在setting全局參數中配置開啟二級緩存。
<code> /<code>
MyBatis的二級緩存是和命名空間綁定的,即二級緩存需要配置在Mapper.xml映射文件或者Mapper接口中。使用元素
在映射文件中,命名空間就是XML根節點mapper的namespace屬性。在Mapper接口中,命名空間就是接口的全限定名稱
配置如下:
- 映射語句文件中的所有SELECT語句將會被緩存
- 映射語句文件中的所有INSERT、UPDATE、DELETE語句會刷新緩存
- 緩存會使用LRU(最近最少使用)策略來回收
- 緩存會被視為read/write(可讀/可寫)的,這意味著對象檢索不是共享的,而且可以安全地被調用者修改,而不干擾其他調用者或線程所做的潛在修改
cache元素屬性如下:
- flushInterval:刷新間隔。可以被設置為任意的正整數,單位毫秒。默認沒有刷新間隔,緩存僅調用語句時刷新
- size:緩存數目。可以被設置為任意正整數。默認值是1024
- readOnly:只讀。該屬性可以被設置為true或false。只讀的緩存會給所有調用者返回緩存對象的相同實例,因此這些對象不能被修改。可讀寫的緩存會返回緩存對象的拷貝。這種方式會慢一些,但是安全,因此默認是false。
- eviction:回收策略,默認為LRU。有如下幾種:
<code>LRU:最近最少使用的策略,移除最長時間不被使用的對象 FIFO: 先進先出策略,按對象進入緩存的順序來移除它們 SOFT: 軟引用策略,移除基於垃圾回收器狀態和軟引用規則的對象 WEAK。 弱引用策略,更積極地移除基於垃圾收集器狀態和弱引用規則的對象 /<code>
MyBatis的註解配置
1.常用註解
- Select:映射查詢的SQL語句
- SelectProvider:select語句的動態SQL映射。允許指定一個類名和 一個方法在執行時返回運行的查詢語句
- Insert:映射插入的SQL語句
- InsertProvider:insert語句的動態SQL映射
- Update:映射更新的SQL語句
- UpdateProvider:update語句的動態SQL映射
- Delete:映射刪除的SQL語句
- DeleteProvider:delete語句的動態SQL映射
- Result:在列和屬性之間的單獨結果映射。屬性包括:id、 column、property、javaType、jdbcType、type Handler、one、many。id 屬性是一個布爾值,表示是否被用於主鍵映射。one 屬性是單獨的映射,和XML配置中的 相似,而many屬性是對集合而言的,和XML配置的相似
- Results:多個結果映射(Result)列表
- Option: 提供配置選項的附加值,它們通常在映射語句上作為附加功能配置
- One:複雜類型的單獨屬性值映射。必須指定select屬性,表示已映射的SQL語句的完全限定名
- Many:複雜類型的集合屬性映射。必須指定select屬性,表示已映射的SQL語句的完全限定名
- Param:當映射器方法需要多個參數時,這個註解可以被應用於映射器方法參數來給每個參數取一個名字。否則,多參數將會以它們的順序位置和SQL語句中的表達式進行映射,這是默認的。使用 @Param("id")時,SQL中參數應該被命名為#{id}
2.select、insert、update、delete註解
3.One註解
關聯映射的對象
被關聯的對象
4.Many註解
關聯映射對象
被關聯的對象
5.存儲過程調用
6.二級緩存