文章目錄
select標籤
在 SQL 映射文件中 < select> 元素用於映射 SQL 的 select 語句,其示例代碼如下:
<!--根據uid查詢一個用戶信息 -->
<select id="selectUserById" parameterType="Integer" resultType="com.mybatis.po.MyUser">
select * from user where uid = #{uid}
</select>
在上述示例代碼中,id 的值是唯一標識符,它接收一個 Integer 類型的參數,返回一個 MyUser 類型的對象,結果集自動映射到 MyUser 屬性。
< select> 元素除了有上述示例代碼中的幾個屬性以外,還有一些常用的屬性,如表 1 所示。
屬性名稱 | 描 述 |
---|---|
id | 它和 Mapper 的命名空間組合起來使用,是唯一標識符,供 MyBatis 調用 |
parameterType | 表示傳入 SQL 語句的參數類型的全限定名或別名。它是一個可選屬性,MyBatis 能推斷出具體傳入語句的參數 |
resultType | SQL 語句執行後返回的類型(全限定名或者別名)。如果是集合類型,返回的是集合元素的類型,返回時可以使用 resultType 或 resultMap 之一 |
resultMap | 它是映射集的引用,與 < resultMap> 元素一起使用,返回時可以使用 resultType 或 resultMap 之一 |
flushCache | 用於設置在調用 SQL 語句後是否要求 MyBatis 清空之前查詢的本地緩存和二級緩存,默認值爲 false,如果設置爲 true,則任何時候只要 SQL 語句被調用都將清空本地緩存和二級緩存 |
useCache | 啓動二級緩存的開關,默認值爲 true,表示將査詢結果存入二級緩存中 |
timeout | 用於設置超時參數,單位是秒(s),超時將拋出異常 |
fetchSize | 獲取記錄的總條數設定 |
statementType | 告訴 MyBatis 使用哪個 JDBC 的 Statement 工作,取值爲 STATEMENT(Statement)、 PREPARED(PreparedStatement)、CALLABLE(CallableStatement) |
resultSetType | 這是針對 JDBC 的 ResultSet 接口而言,其值可設置爲 FORWARD_ONLY(只允許向前訪問)、SCROLL_SENSITIVE(雙向滾動,但不及時更新)、SCROLLJNSENSITIVE(雙向滾動,及時更新) |
使用 Map 接口傳遞多個參數
在實際開發中,查詢 SQL 語句經常需要多個參數,例如多條件查詢。當傳遞多個參數時,< select> 元素的 parameterType 屬性值的類型是什麼呢?在 MyBatis 中允許 Map 接口通過鍵值對傳遞多個參數。
假設數據操作接口中有個實現查詢陳姓男性用戶信息功能的方法:
public List< MyUser> selectAllUser(Map<String,Object> param);
此時,傳遞給映射器的是一個 Map 對象,使用它在 SQL 文件中設置對應的參數,對應 SQL 文件的代碼如下:
<!-- 查詢陳姓男性用戶信息 -->
<select id="selectAllUser" resultType="com.mybatis.po.MyUser">
select * from user
where uname like concat('%',#{u_name},'%')
and usex = #{u_sex}
</select>
在上述 SQL 文件中,參數名 u_name 和 u_sex 是 Map 的 key。
爲了測試該示例,首先創建一個 Web 應用 mybatisDemo02,將 mybatisDemo01 應用的所有 JAR 包複製到 /WEB-INF/lib 下,同時將 mybatisDemo01 應用的 src 目錄下的所有包和文件複製到 mybatisDemo02 應用的 src 目錄下。
然後將 com.mybatis 包中的 SQL 映射文件 UserMapper.xml 中的“查詢所有用戶信息”的代碼片段修改爲上述“查詢陳姓男性用戶信息”的代碼片段,最後將 com.controller 包中 UserController 的代碼簡單修改即可運行測試類了。
com.controller 包中 UserController 的代碼片段如下:
@Controller("UserController")
public class UserController {
private UserDao userDao;
public void test(){
...
//查詢多個用戶
Map<String,Object> map = new HashMap<>();
map.put("u_name","陳");
map.put("u_sex","男");
List<MyUser> list = userDao.seleceAllUser(map);
for(MyUser myUser : list) {
System.out.println(myUser);
}
...
}
}
Map 是一個鍵值對應的集合,使用者要通過閱讀它的鍵才能瞭解其作用。另外,使用 Map 不能限定其傳遞的數據類型,所以業務性不強,可讀性較差。如果 SQL 語句很複雜,參數很多,使用 Map 將很不方便。幸運的是,MyBatis 還提供了使用 Java Bean 傳遞多個參數的形式。
使用 Java Bean 傳遞多個參數
首先在 myBatisSemo02 應用的 src 目錄下創建一個名爲 com.pojo 的包,在包中創建一個 POJO 類 SeletUserParam,代碼如下:
package com.pojo;
public class SeletUserParam {
private String u_name;
private String u_sex;
// 此處省略setter和getter方法
}
接着將 Dao 接口中的 selectAllUser 方法修改爲如下:
public List< MyUser> selectAllUser(SelectUserParam param);
然後將 com.mybatis 包中的 SQL 映射文件 UserMapper.xml 中的“查詢陳姓男性用戶信息”的代碼修改爲如下:
<select id="selectAllUser" resultType="com.po.MyUser" parameterType="com.pojo.SeletUserParam">
select * from user
where uname like concat('%',#{u_name},'%')
and usex=#{u_sex}
</select>
最後將 com.controller 包中 UserController 的“查詢多個用戶”的代碼片段做如下修改:
SeletUserParam su = new SelectUserParam();
su.setU_name("陳");
su.setU_sex("男");
List<MyUser> list = userDao.selectAllUser(su);
for (MyUser myUser : list) {
System.out.println(myUser);
}
在實際應用中是選擇 Map 還是選擇 Java Bean 傳遞多個參數應根據實際情況而定,一般建議選擇 Java Bean。
insert、update、delete和sql標籤
< insert>元素
< insert> 元素用於映射插入語句,MyBatis 執行完一條插入語句後將返回一個整數表示其影響的行數。它的屬性與 < select> 元素的屬性大部分相同,在本節講解它的幾個特有屬性。
- keyProperty:該屬性的作用是將插入或更新操作時的返回值賦給 PO 類的某個屬性,通常會設置爲主鍵對應的屬性。如果是聯合主鍵,可以將多個值用逗號隔開。
- keyColumn:該屬性用於設置第幾列是主鍵,當主鍵列不是表中的第 1 列時需要設置。如果是聯合主鍵,可以將多個值用逗號隔開。
- useGeneratedKeys:該屬性將使 MyBatis 使用 JDBC 的 getGeneratedKeys()方法獲取由數據庫內部產生的主鍵,例如 MySQL、SQL Server 等自動遞增的字段,其默認值爲 false。
1)主鍵(自動遞增)回填
MySQL、SQL Server 等數據庫的表格可以採用自動遞增的字段作爲主鍵,有時可能需要使用這個剛剛產生的主鍵,用於關聯其他業務。
首先爲 com.mybatis 包中的 SQL 映射文件 UserMapper.xml 中 id 爲 addUser 的 < insert> 元素添加 keyProperty 和 useGeneratedKeys 屬性,具體代碼如下:
<!--添加一個用戶,成功後將主鍵值返回填給uid(po的屬性)-->
<insert id="addUser" parameterType="com.po.MyUser" keyProperty="uid" useGeneratedKeys="true">
insert into user (uname,usex) values(#{uname},#{usex})
</insert>
然後在 com.controller 包的 UserController 類中進行調用,具體代碼如下:
// 添加一個用戶
MyUser addmu = new MyUser();
addmu.setUname("陳恆");
addmu.setUsex("男");
int add = userDao.addUser(addmu);
System.out.println("添加了" + add + "條記錄");
System.out.println("添加記錄的主鍵是" + addmu.getUid());
2)自定義主鍵
如果在實際工程中使用的數據庫不支持主鍵自動遞增(例如 Oracle),或者取消了主鍵自動遞增的規則,可以使用 MyBatis 的 < selectKey> 元素來自定義生成主鍵。具體配置示例代碼如下:
<!-- 添加一個用戶,#{uname}爲 com.mybatis.po.MyUser 的屬性值 -->
<insert id="insertUser" parameterType="com.po.MyUser">
<!-- 先使用selectKey元素定義主鍵,然後再定義SQL語句 -->
<selectKey keyProperty="uid" resultType="Integer" order="BEFORE">
select if(max(uid) is null,1,max(uid)+1) as newUid from user)
</selectKey>
insert into user (uid,uname,usex) values(#{uid},#{uname},#{usex})
</insert>
在執行上述示例代碼時,< selectKey> 元素首先被執行,該元素通過自定義的語句設置數據表的主鍵,然後執行插入語句。
< selectKey> 元素的 keyProperty 屬性指定了新生主鍵值返回給 PO 類(com.po.MyUser)的哪個屬性。
- order 屬性可以設置爲 BEFORE 或 AFTER。
- BEFORE 表示先執行 < selectKey> 元素然後執行插入語句。
- AFTER 表示先執行插入語句再執行 < selectKey> 元素。
< update>與< delete>元素
< update> 和 < delete> 元素比較簡單,它們的屬性和 < insert> 元素、< select> 元素的屬性差不多,執行後也返回一個整數,表示影響了數據庫的記錄行數。配置示例代碼如下:
<!-- 修改一個用戶 -->
<update id="updateUser" parameterType="com.po.MyUser">
update user set uname = #{uname},usex = #{usex} where uid = #{uid}
</update>
<!-- 刪除一個用戶 -->
<delete id="deleteUser" parameterType="Integer">
delete from user where uid = #{uid}
</delete>
< sql> 元素
< sql> 元素的作用在於可以定義 SQL 語句的一部分(代碼片段),以方便後面的 SQL 語句引用它,例如反覆使用的列名。
在 MyBatis 中只需使用 < sql> 元素編寫一次便能在其他元素中引用它。配置示例代碼如下:
<sql id="comColumns">id,uname,usex</sql>
<select id="selectUser" resultType="com.po.MyUser">
select <include refid="comColumns"> from user
</select>
在上述代碼中使用 < include> 元素的 refid 屬性引用了自定義的代碼片段。
if標籤
開發人員通常根據需求手動拼接 SQL 語句,這是一個極其麻煩的工作,而 MyBatis 提供了對 SQL 語句動態組裝的功能,恰能解決這一問題。
MyBatis 的動態 SQL 元素與 JSTL 或 XML 文本處理器相似,常用 < if>、< choose>、< when>、< otherwise>、< trim>、< where>、< set>、< foreach> 和 < bind> 等元素。
動態 SQL 通常要做的事情是有條件地包含 where 子句的一部分,所以在 MyBatis 中 < if> 元素是最常用的元素,它類似於 Java 中的 if 語句。在 myBatisDemo03 應用中測試 < if> 元素,具體過程如下:
1)添加 SQL 映射語句
在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射語句:
<!--使用 if 元素根據條件動態查詢用戶信息-->
<select id="selectUserByIf" resultType="com.po.MyUser" parameterType="com.po.MyUser">
select * from user where 1=1
<if test="uname!=null and uname!=''">
and uname like concat('%',#{uname},'%')
</if >
<if test="usex !=null and usex !=''">
and usex=#{usex}
</if >
</select>
2)添加數據操作接口方法
在 com.dao 包的 UserDao 接口中添加如下數據操作接口方法:
public List<MyUser> selectUserByIf(MyUser user);
3)調用數據操作接口方法
在 com.controller 包的 UserController 類中添加如下程序調用數據操作接口方法。
// 使用 if 元素查詢用戶信息
MyUser ifmu=new MyUser();
ifmu.setUname ("張");
ifmu.setUsex ("女");
List<MyUser> listByif=userDao.selectUserByIf(ifmu);
System.out.println ("if元素================");
for (MyUser myUser:listByif) {
System.out.println(myUser);
}
4)測試動態 SQL 語句
運行 com.controller 包中的 TestController 主類,測試動態 SQL 語句。
choose、when、otherwise標籤
有些時候不想用到所有的條件語句,而只想從中擇取一二,針對這種情況,MyBatis 提供了 < choose> 元素,它有點像 Java 中的 switch 語句。在 myBatisDemo03 應用中測試 < choose> 元素,具體過程如下:
1)添加 SQL 映射語句
在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射語句:
<!--使用choose、when、otherwise元素根據條件動態查詢用戶信息-->
<select id="selectUserByChoose" resultType="com.po.MyUser" parameterType= "com.po.MyUser">
select * from user where 1=1
<choose>
<when test="uname!=null and uname!=''">
and uname like concat('%',#{uname},'%')
</when>
<when test="usex!=null and usex!=''">
and usex=#{usex}
</when>
<otherwise>
and uid > 10
</otherwise>
</choose>
</select>
2)添加數據操作接口方法
在 com.dao 包的 UserDao 接口中添加如下數據操作接口方法:
public List<MyUser> selectUserByChoose(MyUser user);
3)調用數據操作接口方法
在 com.controller 包的 UserController 類中添加如下程序調用數據操作接口方法。
// 使用 choose 元素查詢用戶信息
MyUser choosemu=new MyUser();
choosemu.setUname("");
choosemu.setUsex("");
List<MyUser> listByChoose = UserDao.selectUserEyChoose(choosemu);
System.out.println ("choose 元素================");
for (MyUser myUser:listByChoose) {
System.out.println(myUser);
}
4)測試動態 SQL 語句
運行 com.controller 包中的 TestController 主類,測試動態 SQL 語句。
trim、where、set標籤
< trim>元素
< trim> 元素的主要功能是可以在自己包含的內容前加上某些前綴,也可以在其後加上某些後綴,與之對應的屬性是 prefix 和 suffix。
可以把包含內容的首部某些內容覆蓋,即忽略,也可以把尾部的某些內容覆蓋,對應的屬性是 prefixOverrides 和 suffixOverrides。正因爲 < trim> 元素有這樣的功能,所以也可以非常簡單地利用 < trim> 來代替 < where> 元素的功能。
在 myBatisDemo03 應用中測試 < trim> 元素,具體過程如下:
1)添加 SQL 映射語句
在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射語句:
<!--使用trim元素根據條件動態查詢用戶信息-->
<select id="selectUserByTrim" resultType="com.po.MyUser"parameterType="com.po.MyUser">
select * from user
<trim prefix="where" prefixOverrides = "and | or">
<if test="uname!=null and uname!=''">
and uname like concat('%',#{uname},'%')
</if>
<if test="usex!=null and usex!=''">
and usex=#{usex}
</if>
</trim>
</select>
2)添加數據操作接口方法
在 com.dao 包的 UserDao 接口中添加如下數據操作接口方法:
public List<MyUser> selectUserByTrim(MyUser user);
3)調用數據操作接口方法
在 com.controller 包的 UserController 類中添加如下程序調用數據操作接口方法。
// 使用trim元素查詢用戶信息
MyUser trimmu=new MyUser();
trimmu.setUname ("張");
trimmu.setUsex("男");
List<MyUser> listByTrim=userDao.selectUserByTrim(trimmu);
System.out.println ("trim 元素=========================");
for (MyUser myUser:listByTrim) {
System.out.println(myUser);
}
4)測試動態 SQL 語句
運行 com.controller 包中的 TestController 主類,測試動態 SQL 語句。
< where> 元素
< where> 元素的作用是會在寫入 < where> 元素的地方輸出一個 where 語句,另外一個好處是不需要考慮 < where> 元素裏面的條件輸出是什麼樣子的,MyBatis 將智能處理。如果所有的條件都不滿足,那麼 MyBatis 就會查出所有的記錄,如果輸出後是以 and 開頭的,MyBatis 會把第一個 and 忽略。
當然如果是以 or 開頭的,MyBatis 也會把它忽略;此外,在 < where> 元素中不需要考慮空格的問題,MyBatis 將智能加上。
在 myBatisDemo03 應用中測試 < where> 元素,具體過程如下:
1)添加 SQL 映射語句
在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射語句:
<!--使用where元素根據條件動態查詢用戶信息-->
<select id="selectUserByWhere" resultType="com.po.MyUser" parameterType="com.po.MyUser">
select * from user
<where>
<if test="uname != null and uname ! = ''">
and uname like concat('%',#{uname},'%')
</if>
<if test="usex != null and usex != '' ">
and usex=#{usex}
</if >
</where>
</select>
2)添加數據操作接口方法
在 com.dao 包的 UserDao 接口中添加如下數據操作接口方法:
public List<MyUser> selectUserByWhere(MyUser user);
3)調用數據操作接口方法
在 com.controller 包的 UserController 類中添加如下程序調用數據操作接口方法。
// 使用where元素查詢用戶信息
MyUser wheremu=new MyUser();
wheremu.setUname ("張");
wheremu.setUsex("男");
List<MyUser> listByWhere=userDao.selectUserByWhere(wheremu);
System.out.println ("where 元素=========================");
for (MyUser myUser:listByWhere) {
System.out.println(myUser);
}
4)測試動態 SQL 語句
運行 com.controller 包中的 TestController 主類,測試動態 SQL 語句。
< set>元素
在動態 update 語句中可以使用 < set> 元素動態更新列。在 myBatisDemo03 應用中測試 < set> 元素,具體過程如下:
1)添加 SQL 映射語句
在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射語句:
<!--使用set元素動態修改一個用戶-->
<update id="updateUserBySet" parameterType="com.po.MyUser">
update user
<set>
<if test="uname!=null">uname=#{uname}</if>
<if test="usex!=null">usex=#{usex}</if>
</set>
where uid=#{uid}
</update>
2)添加數據操作接口方法
在 com.dao 包的 UserDao 接口中添加如下數據操作接口方法:
public int updateUserBySet(MyUser user);
3)調用數據操作接口方法
在 com.controller 包的 UserController 類中添加如下程序調用數據操作接口方法。
// 使用set元素查詢用戶信息
MyUser setmu=new MyUser();
setmu.setUid (1);
setmu.setUname("張九");
int setup=userDao.updateUserBySet(setmu);
System.out.println ("set 元素修改了"+setup+"條記錄");
System.out.println ("=========================")
4)測試動態 SQL 語句
運行 com.controller 包中的 TestController 主類,測試動態 SQL 語句。
foreach標籤
< foreach> 元素主要用在構建 in 條件中,它可以在 SQL 語句中迭代一個集合。
< foreach> 元素的屬性主要有 item、index、collection、open、separator、close。
- item 表示集合中每一個元素進行迭代時的別名。
- index 指定一個名字,用於表示在迭代過程中每次迭代到的位置。
- open 表示該語句以什麼開始。
- separator 表示在每次進行迭代之間以什麼符號作爲分隔符。
- close 表示以什麼結束。
在使用 < foreach> 元素時,最關鍵、最容易出錯的是 collection 屬性,該屬性是必選的,但在不同情況下該屬性的值是不一樣的,主要有以下 3 種情況:
- 如果傳入的是單參數且參數類型是一個 List,collection 屬性值爲 list。
- 如果傳入的是單參數且參數類型是一個 array 數組,collection 的屬性值爲 array。
- 如果傳入的參數是多個,需要把它們封裝成一個 Map,當然單參數也可以封裝成 Map。Map 的 key 是參數名,collection 屬性值是傳入的 List 或 array 對象在自己封裝的 Map 中的 key。
在 myBatisDemo03 應用中測試 < foreach> 元素,具體過程如下:
1)添加 SQL 映射語句
在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射語句:
<!--使用foreach元素查詢用戶信息-->
<select id="selectUserByForeach" resultType="com.po.MyUser" parameterType=
"List">
select * from user where uid in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
# {item}
</foreach>
</select>
2)添加數據操作接口方法
在 com.dao 包的 UserDao 接口中添加如下數據操作接口方法:
public List<MyUser> selectUserByForeach(List<Integer> listId);
3)調用數據操作接口方法
在 com.controller 包的 UserController 類中添加如下程序調用數據操作接口方法。
//使用foreach元素查詢用戶信息
List<Integer> listId=new ArrayList<Integer>();
listId.add(34);
listId.add(37);
List<MyUser> listByForeach = userDao.selectUserByForeach(listId);
System.out.println ("foreach元素================");
for(MyUser myUser : listByForeach) {
System.out.println(myUser);
}
4)測試動態 SQL 語句
運行 com.controller 包中的 TestController 主類,測試動態 SQL 語句。
bind標籤
在進行模糊查詢時,如果使用“${}”拼接字符串,則無法防止 SQL 注入問題。如果使用字符串拼接函數或連接符號,但不同數據庫的拼接函數或連接符號不同。
例如 MySQL 的 concat 函數、Oracle 的連接符號“||”,這樣 SQL 映射文件就需要根據不同的數據庫提供不同的實現,顯然比較麻煩,且不利於代碼的移植。幸運的是,MyBatis 提供了 < bind> 元素來解決這一問題。
在 myBatisDemo03 應用中測試 < bind> 元素,具體過程如下:
1)添加 SQL 映射語句
在 com.mybatis 包的 UserMapper.xml 文件中添加如下 SQL 映射語句:
<!--使用bind元素進行模糊查詢-->
<select id="selectUserByBind" resultType="com.po.MyUser" parameterType= "com.po.MyUser">
<!-- bind 中的 uname 是 com.po.MyUser 的屬性名-->
<bind name="paran_uname" value="'%' + uname + '%'"/>
select * from user where uname like #{paran_uname}
</select>
2)添加數據操作接口方法
在 com.dao 包的 UserDao 接口中添加如下數據操作接口方法:
public List<MyUser> selectUserByBind(MyUser user);
3)調用數據操作接口方法
在 com.controller 包的 UserController 類中添加如下程序調用數據操作接口方法。
// 使用bind元素查詢用戶信息
MyUser bindmu=new MyUser();
bindmu.setUname ("張");
List<MyUser> listByBind=userDao.selectUserByBind(bindmu);
System.out.println ("bind 元素=========================");
for (MyUser myUser:listByBind) {
System.out.println(myUser);
}
4)測試動態 SQL 語句
運行 com.controller 包中的 TestController 主類,測試動態 SQL 語句。