Mapper映射文件 mapper.xml映射文件主要是用來編寫SQL語句的,以及一些結果集的映射關係的編寫,還有就是緩存的一些配置等等。 在映射文件裡面可以配置以下標簽: | 元素名稱 | 描述 | 備註 | | | | | | select | 查詢語句,最常用、最複雜的元素之一 | 可以自定義 ...
Mapper映射文件
mapper.xml映射文件主要是用來編寫SQL語句的,以及一些結果集的映射關係的編寫,還有就是緩存的一些配置等等。
在映射文件裡面可以配置以下標簽:
元素名稱 | 描述 | 備註 |
---|---|---|
select | 查詢語句,最常用、最複雜的元素之一 | 可以自定義參數,返回結果集等 |
insert | 插入語句 | 執行後返回一個整數,代表插入的條數 |
update | 更新語句 | 執行後返回一個整數,代表更新的條數 |
delete | 刪除語句 | 執行後返回一個整數,代表刪除的條數 |
定義參數映射關係 | 即將被刪除的元素,不建議大家使用 | |
sql | 允許定義一部分的SQL,然後在各個地方引用 | |
resultMap | 用來描述從資料庫結果集中來載入對象,它是它將提供映射規則最複雜、最強大的元素 | 它提供映射規則 |
cache | 給定命名空間的緩存配置 | |
cache-ref | 其他命名空間緩存配置的引用 |
引入映射器
可以在mybatis-config.xml中通過文件路徑引入
<mappers> <mapper resource="mappers/UserMapper.xml"/> </mappers>
通過包名引入
這樣會將mapper下的所有mapper類載入到上下文當中
<mappers> <package name="com.zl.mapper"/> </mappers>
用類註冊引入
<mappers> <mapper class="com.zl.mapper.UserMapper"/> </mappers>
Select標簽
- id
它和 Mapper的命名空間組合起來是唯一的,提供給MyBatis調用。如果命名空間和id組合起來不唯一將拋出異常。 - parameterType
可以給出類的全命名,也可以給出類的別名,但使用別名必須是MyBatis內部定義或者自定義的。 - resultType
定義類的全路徑,在允許自動匹配的情況下,結果集將通過JavaBean的規範映射;也可以定義為int、 double等參數;也可以使用別名,但是要符合別名規範;不能和 resultMap同時使用。 - resultMap
外部 resultMap 的命名引用。 - flushCache
它的作用是在調用SQL後,是否要求清空之前查詢的本地緩存和二級緩存 - useCache
將其設置為 true,將會導致本條語句的結果被二級緩存,預設值:true。 - timeout
這個設置是在拋出異常之前,驅動程式等待資料庫返回請求結果的秒數。預設值為 unset(依賴驅動)。 - fetchSize
這是嘗試影響驅動程式每次批量返回的結果行數和這個設置值相等。預設值為 unset(依賴驅動)。 - statementType
STATEMENT,PREPARED 或 CALLABLE 的一個。這會讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,預設值:PREPARED。 - resultSetType
FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一個,預設值為 unset (依賴驅動)。 - databaseId
如果配置了 databaseIdProvider,MyBatis 會載入所有的不帶 databaseId 或匹配當前 databaseId 的語句;如果帶或者不帶的語句都有,則不帶的會被忽略。 - resultOrdered
這個設置僅針對嵌套結果 select 語句適用:如果為 true,就是假設包含了嵌套結果集或是分組了,這樣的話當返回一個主結果行的時候,就不會發生有對前面結果集的引用的情況。這就使得在獲取嵌套的結果集的時候不至於導致記憶體不夠用。預設值:false。 - resultSets
這個設置僅對多結果集的情況適用,它將列出語句執行後返回的結果集並每個結果集給一個名稱,名稱是逗號分隔的。
自動映射
自動映射可以在settings元素中配置autoMappingBehavior屬性值來設置其策略:
- NONE,取消自動映射。
- PARTIAL(預設值),只會自動映射,沒有定義嵌套結果集映射的結果集。
- FULL,會自動映射任意複雜的結果集(無論是否嵌套),在性能上會下降。
Insert標簽
insert的很多配置元素是和select一樣的,就不再贅述,下麵列出select中沒有的屬性
keyProperty
表示以哪個列作為屬性的主鍵,不能和keyColumn同時使用
keyColumn
表示第幾列是主鍵,不能和keyProperty同時使用
useGeneratedKeys
這會令MyBatis使用JDBC的getGeneratedKeys方法來取出由資料庫內部生成的主鍵,但是使用它就必須要給keyProperty或者 keyColumn賦值
主鍵回填
方式一
<insert id="insertBook" useGeneratedKeys="true" keyProperty="id">
insert into t_book (b_name,author) values (#{name},#{author});
</insert>
這種方式比較簡單,就是在插入節點上添加 useGeneratedKeys 屬性,同時設置接收回傳主鍵的屬性。配置完成後,我們執行一個插入操作,插入時傳入一個對象,插入完成後,這個對象的 id 就會被自動賦值,值就是剛剛插入成功的id。
推薦大家使用這種方式,原因很簡單,這種方式實現簡便省事。
方式二
第二種方式則是利用MySQL自帶的 last_insert_id() 函數查詢剛剛插入的id,示例代碼如下:
<insert id="insertBook">
<selectKey keyProperty="id" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
insert into t_book (b_name,author) values (#{name},#{author});
</insert>
這種方式是在 insert 節點中添加 selectKey 來實現主鍵回填,實際上這種方式的功能更加豐富,因為 selectKey 節點中的 SQL 我們既可以在插入之前執行,也可以在插入之後執行(通過設置節點的 Order 屬性為 AFTER 或者 BEFORE 可以實現),具體什麼時候執行,還是要看具體的需求,如果是做主鍵回填,我們當然需要在插入 SQL 執行之後執行 selectKey 節點中的 SQL。
註意第二種方式一樣也要通過設置 keyProperty 來指定將查詢到的數據綁定到哪個屬性上。
參數配置
我們可以傳入一個簡單的參數如基本類型和字元串;也可以傳入JavaBean;還可以指定特定的類型,以確定使用哪個 typeHandler處理它們。定義參藪屬性的時候,MyBatis不允許換行。
{age, javaType=int, jdbcType=NUMERIC}
- 指定typeHandler:#{age, javaType=int, jdbcType=NUMERIC, typeHandler=MyTypeHandler}
- 數值型的參數設置其保存的精度:#{price, javaType=double, jdbcType=NUMERIC, numericScale=2}
resultMap結果映射集
resultMap裡面標簽如下圖所示:
- constructor元素用於配置構造方法,一個POJO可能不存在無參數的構造方法,這個時候我們就可以使用 constructor進行配置。
- id元素是表示哪個列是主鍵,允許多個主鍵構成聯合主鍵。
result是配置POJO到SQL列名的映射關係。
association代表一對一關係,比如每個班級都有一個班長
collection代表一對多關係,比如每個班級有多個學生
discriminator鑒別器,它可以根據實際選擇採用哪個類作為實例,允許你根據特定的條件去關聯不同的結果集合
延遲載入
全局延遲載入
為了處理N+1的問題,My Batis引入了延遲載入的功能。延遲載入功能的意義在於,開始並不取出級聯數據,只有當使用它了才發送SQL去取回數據。MyBatis的配置中有兩個全局的參數lazyLoadingEnabled和aggressiveLazyLoading。
- lazyLoadingEnabled的含義是是否開啟延遲載入功能;
- aggressiveLazyLoading的含義是對任意延遲屬性的調用會使帶有延遲載入屬性的對象完整載入;反之,每種屬性將按需載入。
局部延遲載入
由於全局配置的靈活性較差,MyBatis提供了局部延遲載入的功能。我們可以在association和 collection元素上加入屬性值fetchType就可以了。
緩存
一級緩存
- MyBatis對緩存提供支持,在沒有配置的預設的情況下,它只開啟一級緩存(一級緩存只是相對於同一個 SqlSession而言),所以在參數和SQL完全一樣的情況下,我們使用同一個 SqlSession對象調用同一個Mapper的方法,往往只執行一次SQL。
- 使用SqlSession第一次查詢後,MyBatis會將其放在緩存中。以後再查詢的時候,如果沒有聲明需要刷新且緩存沒超時,SqlSession都只會取出當前緩存的數據,而不會再次發送SQL到資料庫。
- 如果使用的是不同的SqlSession對象,因為不同的SqlSession都是相互隔離的,所以用相同的 Mapper、參數和方法,它還是會再次發送SQL到資料庫去執行。
- 當我們關閉SqlSession對象後,緩存就會失效。
二級緩存
一級緩存在各個SqlSession間是相互隔離的。為了剋服這個問題,我們往往需要配置二級緩存,使得緩存在SqlsessionFactory層面上能夠提供給各個SqISession對象共用,二級緩存預設是不開啟的。
- 二級緩存的時候要求返回的POJO必須是可序列化的,也就是要求實現Serializable介面。
- 配置的緩存的方法很簡單,只需要在Mapper.xml文件中加入
<cache/>
。 - 映射語句文件中的所有insert、update和delete語句會刷新緩存