Mybatis 能夠說是 Java 後端的必備技能,可能你和我同樣常常使用到它。但有時 cv 多了,會忘記了一些細節處理,好比爲何要加上這個註解?它的做用是什麼等等。git
這篇文章是我之前寫的一些關於 Mybatis 細節,但願對各位有起到查漏補缺的做用。github
SqlMapConfig.xml 文件各參數介紹:spring
?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 加載屬性文件 --> <properties resource="jdbc.properties"> <!--properties中還能夠配置一些屬性名和屬性值 --> <!-- <property name="jdbc.driver" value=""/> --> </properties> <!-- 全局配置參數,須要時再設置 --> <settings> <!-- 打開延遲加載的開關,默認爲false --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 將積極加載改成消極加載即按須要加載,默認爲true --> <setting name="aggressiveLazyLoading" value="false"/> <!-- 開啓二級緩存,默認爲true --> <setting name="cacheEnabled" value="true"/> <!-- 使用jdbc的getGeneratedKeys獲取數據庫自增主鍵值 --> <setting name="useGeneratedKeys" value="true"/> </settings> <!-- 別名定義 --> <typeAliases> <!-- 針對單個別名定義 type:類型的路徑 alias:別名 --> <!-- <typeAlias type="com.iot.mybatis.po.User" alias="user"/> --> <!-- 批量別名定義 指定包名,mybatis自動掃描包中的po類,自動定義別名,別名就是類名(首字母大寫或小寫均可以) --> <package name="com.iot.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.iot.mybatis.mapper"/> <mappers/>
使用 #{parameterName} 引用參數的時候,Mybatis 會把這個參數認爲是一個字符串,例如在下面的 sql 傳入參數 「Smith」,
Select from emp where name = #{employeeName}sql
就會被轉換爲:
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}%'mybatis
上面話有點長,這裏小小總結下:
#{} :編譯好 SQL 語句再取值
${} :取值之後再去編譯SQL語句
好比:name 字段。
解決方法:在列名兩邊加上兩個 ` 便可,以下:
DELETE FROM stu WHERE name
LIKE '%${name}%'
那麼爲何會致使查詢的 SQL 語句沒法獲得正確結果呢?
由於 mybatis 會經過反射獲得 bean ,因爲字段名和屬性名不同,致使沒法將查詢到的表字段數據 set 到 bean 屬性中。
解決方法:
【不推薦】修改表字段名稱或 bean 屬性名稱,使它們同名便可
【推薦】修改 標籤中的相應內容,以下圖所示
做用:至關於給其修飾的參數指定一個別名。
若接口只有一個參數則能夠不用指定別名,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 能夠是任意的。
參考:
歡迎關注微信公衆號「不僅Java」,後臺回覆「電子書」,送說不定有你想要的呢