MyBatis3+ 實現批量更新
阿新 • • 發佈:2018-11-23
要實現批量更新,首先得設定mysql支援批量操作,在jdbc連結中需要附加
&allowMultiQueries=true
屬性才行
例如:
jdbc:mysql://localhost:3306/dbname?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
- 更新單條記錄
UPDATE course SET name = 'course1' WHERE id = 'id1';
- 更新多條記錄的同一個欄位為同一個值
UPDATE course SET name = 'course1' WHERE id in ('id1', 'id2', 'id3);
- 更新多條記錄為多個欄位為不同的值
比較普通的寫法,是通過迴圈,依次執行update語句。
Mybatis寫法如下:
<update id="updateBatch" parameterType="java.util.List">
<foreach collection="list" item="item" index="index" open="" close="" separator=";">
update course
<set>
name=${item.name}
</set >
where id = ${item.id}
</foreach>
</update>
一條記錄update一次,效能比較差,容易造成阻塞。
- MySQL沒有提供直接的方法來實現批量更新,但可以使用
case when
語法來實現這個功能。
UPDATE course
SET name = CASE id
WHEN 1 THEN 'name1'
WHEN 2 THEN 'name2'
WHEN 3 THEN 'name3'
END,
title = CASE id
WHEN 1 THEN 'New Title 1'
WHEN 2 THEN 'New Title 2'
WHEN 3 THEN 'New Title 3'
END
WHERE id IN (1,2,3)
這條sql的意思是,如果id為1,則name的值為name1,title的值為New Title1;依此類推。
在Mybatis中的配置則如下:
<update id="updateBatch" parameterType="list">
update course
<trim prefix="set" suffixOverrides=",">
<trim prefix="peopleId =case" suffix="end,">
<foreach collection="list" item="i" index="index">
<if test="i.peopleId!=null">
when id=#{i.id} then #{i.peopleId}
</if>
</foreach>
</trim>
<trim prefix=" roadgridid =case" suffix="end,">
<foreach collection="list" item="i" index="index">
<if test="i.roadgridid!=null">
when id=#{i.id} then #{i.roadgridid}
</if>
</foreach>
</trim>
<trim prefix="type =case" suffix="end," >
<foreach collection="list" item="i" index="index">
<if test="i.type!=null">
when id=#{i.id} then #{i.type}
</if>
</foreach>
</trim>
<trim prefix="unitsid =case" suffix="end," >
<foreach collection="list" item="i" index="index">
<if test="i.unitsid!=null">
when id=#{i.id} then #{i.unitsid}
</if>
</foreach>
</trim>
</trim>
where
<foreach collection="list" separator="or" item="i" index="index" >
id=#{i.id}
</foreach>
</update>
上面是使用xml配置檔案進行的批量修改,另外,更詳細的介紹可以參考這位老哥哥的部落格
下面看使用註解如何寫批量更新操作:
使用註解批量更新
首先定義批量更新的介面,引數使用@Param
註解界定;
public interface WarningMapper {
@UpdateProvider(method = "updateBatch", type = WarningProvider.class)
int updateBatch(@Param(value = "list") List<WarningModel> records);
}
提供provider:
class WarningProvider {
public String updateBatch(final Map<String, List<WarningModel>> map) {
List<WarningModel> records = map.get("list");//注意這裡引數是map獲取list
StringBuilder sb = new StringBuilder();
sb.append("update " + TABLE_NAME);
sb.append(" set now_value = case appid");//這裡可以仿照set now_value 設定其他值的修改
MessageFormat mfNowValue = new MessageFormat("#'{'list[{0}].now_value'}'");
for (int i = 0; i < records.size(); i++) {
sb.append(" when ");
sb.append(records.get(i).getAppid());
sb.append(" then ");
sb.append(mfNowValue.format(new Object[] { i }));
}
sb.append(" end ");
sb.append("where appid in");
sb.append("(");
for (int size = 0; size < records.size(); size++) {
sb.append(records.get(size).getAppid());
if (size < records.size() - 1) {
sb.append(",");
}
}
sb.append(")");
return sb.toString();
}
}
上面主要注意表示式"#'{'list[{0}].now_value'}'"
的使用
批量插入操作也可以參考批量更新,比較簡單不需要case語句
這裡在介紹一下Mybatis的常用註解
MyBatis常用註解
- 查詢註解@Select
- 刪除註解@Delete
- 插入註解@Insert
- 更新註解@Update
- @[email protected]@[email protected]
- @Options註解
@Options常用屬性:
- flushCache:重新整理快取策略,有
DEFAULT
,TRUE
,FALSE
三種值,預設DEFAULT
表示重新整理查詢語句的快取 - useCache:預設true,表示使用快取
- fetchSize:查詢時的獲取數量
- useGeneratedKeys:預設false,是否返回插入的id
- keyProperty:實體類id屬性
- keyColumn:實體類屬性對應資料庫的欄位
舉例:一個插入資料操作的mapper定義如下:
public interface WarningMapper {
@Insert(value = "insert into dtjx_warning"
+ " (trans_id,monitor_type,creator,created,filter,version)"
+ " values (#{trans_id},#{monitor_type},#{creator},#{created},#{filter},version+1)")
@Options(keyProperty = "appid", useGeneratedKeys = true, keyColumn = "appid") // 用options屬性的useGenerateKeys可以返回自動增長的主鍵資訊
int insert(WarningModel record);
}
更多註解使用方法,請參考官方文件