【本人禿頂程式設計師】這也許是你不曾留意過的 Mybatis 細節
←←←←←←←←←←←← 我都禿頂了,還不點關注!
Mybatis 可以說是 Java 後端的必備技能,可能你和我一樣經常使用到它。但有時 cv 多了,會忘記了一些細節處理,比如為什麼要加上這個註解?它的作用是什麼等等。
這篇文章是我以前寫的一些關於 Mybatis 細節,希望對各位有起到查漏補缺的作用。
1. 配置檔案
SqlMapConfig.xml 檔案各引數介紹:
<configuration> <!-- 載入屬性檔案 --> <properties resource="jdbc.properties"> <!--properties中還可以配置一些屬性名和屬性值 --> <!-- <property name="jdbc.driver" value=""/> --> </properties> <!-- 全域性配置引數,需要時再設定 --> <settings> <!-- 開啟延遲載入的開關,預設為false --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 開啟二級快取,預設為true --> <setting name="cacheEnabled" value="true"/> <!-- 使用jdbc的getGeneratedKeys獲取資料庫自增主鍵值 --> <setting name="useGeneratedKeys" value="true"/> </settings> <!-- 別名定義 --> <typeAliases> <!-- 針對單個別名定義 type:型別的路徑,alias:別名。示例:--> <typeAlias type="com.czd.mybatis.po.User" alias="user"/> <!-- 批量別名定義 指定包名,mybatis自動掃描包中的po類,自動定義別名,別名就是類名(首字母大寫或小寫都可以)--> <package name="com.czd.mybatis.po"/> </typeAliases> <!-- 和spring整合後 environments配置將廢除--> <environments default="development"> <environment id="development"> <!-- 使用jdbc事務管理,事務控制由mybatis--> <transactionManager type="JDBC"/> <!-- 資料庫連線池,由mybatis管理--> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <!--載入對映檔案有 3 種方法,如下所示--> <mappers> <mapper resource="sqlmap/User.xml"/> <!--1. 通過 resource 方法一次載入一個對映檔案 --> <!-- <mapper resource="mapper/UserMapper.xml"/> --> <!-- 2. 通過 mapper 介面載入單個對映檔案 遵循一些規範:需要將 mapper 介面類名和 mapper.xml 對映檔名稱保持一致,且在一個目錄中 --> <!-- <mapper class="com.iot.mybatis.mapper.UserMapper"/> --> <!-- 3. 批量載入 mapper 指定 mapper 介面的包名,mybatis 自動掃描包下邊所有 mapper 介面進行載入 遵循一些規範:需要將 mapper 介面類名和 mapper.xml對映檔名稱保持一致,且在一個目錄中 --> <package name="com.czd.mybatis.mapper"/> <mappers/>
2. # 和 $ 的區別
使用 #{parameterName} 引用引數的時候,Mybatis 會把這個引數認為是一個字串,例如在下面的 sql 傳入引數 “Smith”,
Select from emp where name = #{employeeName}
就會被轉換為:
Select from emp where name = ‘Smith’;
同理在下面 sql 傳入引數 “Smith”:
Select from emp where name = ${employeeName}
使用的時候就會被轉換為 :
Select from emp where name = Smith;
簡單來說, #{} 是經過預編譯的,是安全的,而 ${} 是未經過預編譯的,僅僅是取變數的值,是非安全的,存在 sql 注入的危險。# 將傳入的資料都當成一個字串,會對自動傳入的資料加一個雙引號。
使用 ${} 的情況,order by、like 語句只能用 ${} 了,用 #{} 會多個 ’ ’ 導致 sql 語句失效.此外動態拼接 sql,模糊查詢時也要用 ${}。
舉個栗子,假如 name=陳,那麼該 sql 就是 … LiKE ‘%陳%’,
DELETE FROM stu WHERE `name` LIKE '%${name}%'
3.SQL 語句中的列名與關鍵字衝突時怎麼辦
比如:name 欄位。
解決方法:在列名兩邊加上兩個 ` 即可,如下:
DELETE FROM stu WHERE `name` LIKE '%${name}%'
4.列名和 bean 屬性名不一樣,導致獲取不到資料時怎麼辦
那麼為什麼會導致查詢的 SQL 語句無法得到正確結果呢?
因為 mybatis 會通過反射得到 bean ,由於欄位名和屬性名不一樣,導致無法將查詢到的表字段資料 set 到 bean 屬性中。
解決方法:
【不推薦】修改表字段名稱或 bean 屬性名稱,使它們同名即可
【推薦】修改 標籤中的相應內容,如下圖所示
5. @Param 引數的作用
作用:相當於給其修飾的引數指定一個別名。
若介面只有一個引數則可以不用指定別名,List 引數除外。當有多個引數時一定要指定,否則 mybatis 對映不到對應的欄位。
如下程式碼:
List<Book> queryAll(@Param("offset")int offset, @Param("limit")int limit);
該介面方法對應的 mapper 實現如下:
<select id="queryAll" resultType="Book">
SELECT
book_id,
`name`,
`number`
FROM
book
ORDER BY
book_id
LIMIT #{offset}, #{limit}
</select>
可以看到 #{} 裡面的值是和 @Param(“value”) 保持一致的,也一定要一致,否則 mybatis 會找不到這個值而導致報錯。另外,@Param(“value”) 中的 value 可以是任意的。