mysqlupdate多条件批量更新_Mybatis中进⾏批量更新
(updateBatch)
更新多条数据,每条数据都不⼀样
背景描述:通常如果需要⼀次更新多条数据有两个⽅式,(1)在业务代码中循环遍历逐条更新。(2)⼀次性更新所有数据(更准确的说是⼀条sql语句来更新所有数据,逐条更新的操作放到数据库端,在业务代码端展现的就是⼀次性更新所有数据)。两种⽅式各有利弊,下⾯将会对两种⽅式的利弊做简要分析,主要介绍第⼆种⽅式在mybatis中的实现。
逐条更新(效率低)(⽅法⼀)
这种⽅式显然是最简单,也最不容易出错的,即便出错也只是影响到当条出错的数据,⽽且可以对每条数据都⽐较可控,更新失败或成功,从什么内容更新到什么内容,都可以在逻辑代码中获取。代码可能像下⾯这个样⼦:
1 updateBatch(Listdatas){
2 for(MyData data : datas){
3 try{
4 myDataDao.update(data);//更新⼀条数据,mybatis中如下⾯的xml ⽂件的update
5 }
6 catch(Exception e){
7 ...//如果更新失败可以做⼀些其他的操作,⽐如说打印出错⽇志等
8 }
9 }10 }11
12 //mybatis中update操作的实现13
14 update mydata15 set ...16 where (17)
这种⽅式最⼤的问题就是效率问题,逐条更新,每次都会连接数据库,然后更新,再释放连接资源(虽然通过连接池可以将频繁连接数据的效率⼤⼤提⾼,抗不住数据量⼤),这中损耗在数据量较⼤的时候便会体现出效率问题。这也是在满⾜业务需求的时候,通常会使⽤上述提到的第⼆种批量更新的实现(
当然这种⽅式也有数据规模的限制,后⾯会提到)。
逐条更新(⽅法⼆)
通过循环,依次执⾏多条update的sql
前提条件:
要实现批量更新,⾸先得设置mysql⽀持批量操作,在jdbc链接中需要附加&allowMultiQueries=true属性才⾏
例如:
jdbc:mysql://localhost:3306/dbname?
characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
1
2
3 update course4
5 name=${item.name}6
7 where id = ${item.id}8
9
⼀条记录update⼀次,性能⽐较差,容易造成阻塞。
sql批量更新(⼀)(主⼒)
(可⾏)实际实践(传⼊的是List>)
++务必注意:⼀定要加where条件,⾥⾯的id为需要更新的数据的id;如果不加where条件,则会全部更新,但是需要更新且有数据的更新为传递的数据,没有数据的则更新为null,此时更新出错++
1
2 update followme_parameters3
5
6
7 when account=#{item.account} and chart_id=#{item.chartId}8 then #{item.signalSource}9
10
11
12
13
14
15 when account=#{item.account} and chart_id=#{item.chartId}16 then #{item.rate}17
18
19
20
21 where id in22
23 #{item.id}24
25
下⾯逐步讲解
⼀条sql语句来批量更新所有数据,下⾯直接看⼀下在mybatis中通常是怎么写的(去掉mybatis语法就是原⽣的sql语句了,所有就没单独说sql是怎么写的)。
1
2 update mydata_table
3 set status=4
5 separator=" "open="case ID"close="end">
6 when #{item.id} then #{item.status}7
8 where id in9
10 separator=","open="("close=")">
11 #{item.id,jdbcType=BIGINT}12
13
其中是sql中的"switch" 语法。这⾥借助mybatis的语法来拼凑成了批量更新的sql,上⾯的意思就是批量更新id在updateBatch参数所传递List中的数据的status字段。还可以使⽤实现同样的功能,代码如下:
1
2 update mydata_table3
4
5
6 when id=#{item.id} then #{item.status}7
8
10 where id in11
sql中update什么意思12 #{item.id,jdbcType=BIGINT}13
14
15
16
属性说明
1.prefix,suffix 表⽰在trim标签包裹的部分的前⾯或者后⾯添加内容
2.如果同时有prefixOverrides,suffixOverrides 表⽰会⽤prefix,suffix覆盖Overrides中的内容。
3.如果只有prefixOverrides,suffixOverrides 表⽰删除开头的或结尾的xxxOverides指定的内容。
上述代码转化成sql如下:
1 update mydata_table
2 set status =
3 case
4 when id = #{item.id} then #{item.status}//此处应该是展开值
5 ...
6 end
7 where id in (...);
当然这是最简单的批量更新实现,有时候可能需要更新多个字段,那就需要将
1
2
3 when id=#{item.id} then #{item.status}4
5
复制拷贝多次,更改prefix和的内容即可.⽽如果当需要为某个字段设置默认值的时候可以使⽤else
1
2
3 when id=#{item.id} then #{item.status}4
5 else default_value6
还有更常见的情况就是需要对要更新的数据进⾏判断,只有符合条件的数据才能进⾏更新,这种情况可以这么做:
1
2
3
4 when id=#{item.id} then #{item.status}5
6
7
这样的话只有要更新的list中status != null && status != -1的数据才能进⾏status更新.其他的将使⽤默认值更新,⽽不会保持原数据不变.如果要保持原数据不变呢?即满⾜条件的更新,不满⾜条件的保持原数据不变,简单的来做就是再加⼀个,因为mybatis中没有if...语法,但可以通过多个实现同样的效果,如下:
1
2
4 when id=#{item.id} then #{item.status}5
6
7 when id=#{item.id} then mydata_table.status //这⾥就是原数据8
9
10
整体批量更新的写法如下: (亲测有效)
1
2 update mydata_table3
4
5
6
7 when id=#{item.id} then #{item.status}8
9
10 when id=#{item.id} then mydata_table.status//原数据11
12
13
14
15 where id in16
17 #{item.id,jdbcType=BIGINT}18
19
批量更新(单个字段,传参list),实际是sql批量更新的简化版本⽽已
单个字段
update t_goods
set NODE_ID=when GOODS_ID=#{dsId} then #{deId}where GOODS_ID in#{dsId,jdbcType=BIGINT}单个字段⽅法⼆
UPDATE
t_goods
SET NODE_ID = CASEWHEN GOODS_ID = #{dsId} THEN #{deId}END
WHERE GOODS_ID IN#{dsId}
以上单字段更新实际执⾏:
UPDATE t_goods SET NODE_ID = CASE WHEN GOODS_ID = ? THEN ? END WHERE GOODS_ID IN ( ? )
sql批量更新(⼆)
传⼊的是List>
直接运⾏插⼊,如果有插⼊的数据转为更新该条数据
1
2 insert into followme_parameters
3 (account,chart_id,signal_source,rate)
4 values5
6 (#{item.account},#{item.chartId},#{item.signalSource},#{item.rate})7
8 ON duplicate KEY UPDATE9 signal_source=values(signal_source),rate=values(rate)10 11
更新多条数据,更新的内容⼀样.
⽅法⼀,传map/ 传String
NODE_ID从map中取出来,goodsIdList是字符串拼接好的(如下⾯的"1,2,5")
UPDATE t_goods
SET NODE_ID = #{nodeId}
WHERE GOODS_ID IN (${goodsIdList})
实际的sql
1 UPDATE t_goods SET NODE_ID = ? WHERE GOODS_ID IN (1,2,5);
⽅法⼆,传map/传list
NODE_ID从map中取出来,goodsIdList是⽤list拼接出来的
1
2 UPDATE t_goods
3 SET NODE_ID = #{nodeId}
4 WHERE GOODS_ID IN5
6 #{dsId}7
8
实际的sql
UPDATE t_goods SET NODE_ID = ? WHERE GOODS_ID IN (1,2,5);
站在巨⼈的肩膀上摘苹果:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论