文章目錄
# 入門:簡單 靜態 SQL 映射
## 獲取 新增數據id? (MySQL 、 Oracle)
原生 使用 statement 的方法
mysql 支持自增主鍵,自增主鍵值的獲取,mybatis 也是利用 statement.getGeneratedKey()
useGeneratedKeys="true"
使用自增組件獲取主鍵值策略keyProperty
指定對應的主鍵屬性,也就是 mybatis 獲取到主鍵值以後,封裝到 javaBean 的哪個屬性keyColumn
指定 數據庫查出的表中,哪一列是 id
Oracle 怎麼搞?
## @Param
-
POJO:
如果多個參數正好是我們業務邏輯的數據模型,我們就可以直接傳入 pojo
#{屬性名}:取出傳入的 pojo 的屬性值 -
Map:
如果多個參數不是業務模型中的數據,沒有對應的 pojo ,爲了方便傳入 map
#{key}:取出key 對應的 value -
TO:
如果多個參數不是業務模型中的數據,但是經常要使用,推薦來編寫一個 TO(Transfer Object) 數據傳輸對象class Page{ int index; int size; }
文章目錄
# 進階1(@Param 和 參數名映射 源碼分析)
以 selectById 爲例,step into
來到 MapperProxy
的 invoke 方法
MapperProxy
實現了InvocationHandler
接口
當前要執行的方法 ⇒ 參數 method
繼續看 invoke 方法 (下面圖)
第一行 Object.class.equals(method.getDeclaringClass())
判斷如果是 Object 的方法(如 toString 方法)
直接放行
否則,進行處理(下圖)
首先,final MapperMethod mapperMethod = cachedMapperMethod(method);
把 method 包裝成 MapperMethod
(這塊不是重點,暫時跳過)
看上圖 第二句代碼 mapperMethod.execute(sqlSession, args);
作用:執行mapper方法
先看傳入的參數
args 的 1 是我們傳入的 參數 id
sqlsession
下面 step into execute
方法
從 command 裏面獲取數據
知道是 增刪查改的 哪個方法(這裏是 select)
首先會執行執行 method.convertArgsToSqlCommandParam(args)
(看下圖)
把 args 傳入的 參數 轉換爲 param sql語句
select 方法有點特殊(下圖)
會先判斷返回類型
返回 void?多個?Map?圖標(Cursor)?或者一個對象(else)
可以看到(下圖)
查詢一個的情況,底層調用的 還是 sqlSession 的 selectOne 方法 ()
只不過 這裏需要傳入的是 處理好的 param
所以 , step into method.convertArgsToSqlCommandParam(args);
看看是怎麼玩的
可以看到(上圖)
names 已經有值了
值怎麼來的?
ParamNameResolver
構造時候 賦值的(下圖)
(上圖)最後,map 把 name 值 put 進去
然後 上面 有 isUseActualParamName 方法,值 根據 配置 確定的
如果配置了爲
true
並且是jdk1.8
之後的。
那麼,就使用方法簽名中的名稱作爲語句參數名稱
好,知道 names 的值是怎麼來的了,
現在 ,回到 getNamedParams
方法 (下圖)
第一層 if 判斷 args 的數目
如果 數目爲0 ⇒ return null
如果 數目爲1 ⇒ 返回第一個
否則 遍歷取值
如:names={0=id,1=lastName}
⇒ param={id:args[0] , lastName:args[1]}
前者用於 匹配參數名,後者用於 根據參數名 找 參數值
文章目錄
# 入門 :#{} 和 ${} 的區別
- #{}:是以預編譯的形式,將參數設置到 sql 語句中,PreparedStatement 防止 sql 注入
- ${}:取出的值直接拼裝在 sql 語句中;會有安全問題
但也有使用情況:
如 列名的拼接
select * from ${year}_salary where xxx;
select * from tbl_employee order by ${f_name} ${order} ;
#{}:更豐富的用法
規定參數的一些規則:
## JdbcType.class
jdbcType 通常需要在某種特定條件下被設置:
在我們數據爲 null 的時候, 有些數據庫(如Oracle)可能不能識別 mybatis 對 null 的默認處理
如 Oracle 在這種情況下就會報錯
原因:JdbcType OTHER , 無效的類型,因爲 mybatis 對所有的 null 映射都是 原生 Jdbc 的 OTHER 類型。而 Oracle 無法識別 OTHER 類型
在 JdbcType.class 裏面可以看到所有的 類型
對於 上面 Oracle 不支持 OTHER 類型,
解決方法有兩個如下:
-
(在 #{…} 裏面 加
jdbcType=NULL
)
-
全局配置(jdbcTypeForNull)
文章目錄
# 入門:map映射
第一種 map 映射(【一條數據】key:屬性名、value:屬性值)
第二種 map 映射(【多條數據】key:對象 id、value:對象)
文章目錄
# 入門:select 標籤 中的屬性
文章目錄
# 入門 :resultMap
resultMap resultType 只能 二選一
文章目錄
# 入門:resultMap - 級聯 - 一對多
文章目錄
# 入門:association 聯合 查詢
文章目錄
# 入門:association 分步查詢(爲延時加載做鋪墊)
# 入門:延時加載(按需加載)
上面的 分步查詢有一個問題
:我們每次查詢 Employee 對象的時候,將把 Dept 一起查詢出來。
我們希望,部門信息在我們使用的時候再去查詢。
.
實現起來其實很簡單。
只需要在 分段查詢的基礎上 加上兩個配置
lazyLoadingEnabled
懶加載 。 設置所有的懶加載aggressiveLazyLoading
如果開啓,懶加載也會完全的加載全部屬性。否則,只有需要時候才加載
文章目錄
# 入門:collection 聯合查詢
文章目錄
# 入門:collection 分步查詢
## 傳多列時候怎麼搞?
## fetchType
文章目錄
# 入門:discriminator 鑑別器
鑑別器:mybatis 可以使用 discriminator 判斷某列的值,然後根據某列的值改變封裝行爲
封裝 Employee:
如果查出的是女生,就把部門信息查詢出來,否則不查詢
如果是男生,把 last_name 這一列的值賦值給 email