Mybatis批量更新对象数据的两种实现方式
作者:何中应
这篇文章主要介绍了Mybatis批量更新对象数据的两种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
说明:
遇到一次需要批量修改对象的场景。
传递一个对象集合,需要根据对象ID批量修改数据库数据,使用的是MyBatis框架。查了一些资料,总结出两种实现方式。
创建Demo
首先,创建一个简单的Demo;
(User,用户对象)
import lombok.Data; import java.io.Serializable; @Data public class User implements Serializable { private String id; private String username; private String password; }
(UserController,用户控制器)
@RestController @RequestMapping("/user") public class UserController { @Autowired private UserMapper userMapper; /** * 根据ID查询用户 * @param id * @return */ @GetMapping("/getUser/{id}") public String getUser(@PathVariable("id") String id){ return userMapper.getUser(id).toString(); } }
(UserMapper,用户数据访问接口)
import com.hezy.pojo.User; import org.apache.ibatis.annotations.Mapper; @Mapper public interface UserMapper { User getUser(String id); }
数据库数据,tb_user
表
项目启动,测试一下接口,没得问题;
批量更新
创建一个新的接口,用于触发批量更新对象的代码,内容是传递一个List集合对象给Mapper处理;
@GetMapping("/updateUser") public void updateUser(){ ArrayList<User> users = new ArrayList<>(); User user1 = new User(); user1.setId("1"); user1.setUsername("zhangsan_fix"); User user2 = new User(); user2.setId("2"); user2.setUsername("lisi_fix"); user2.setPassword("654321_fix"); users.add(user1); users.add(user2); userMapper.updateUser(users); }
接下来,重点是Mapper.xml中的Statement要怎么写,继续往下看
方式一
首先,我们可以使用动态SQL,如下:
<update id="updateUser"> <foreach collection="users" item="user" separator=";"> update tb_user <set> <if test="user.username != null and user.username != ''"> username = #{user.username}, </if> <if test="user.password != null and user.password != ''"> password = #{user.password} </if> </set> where id = #{user.id} </foreach> </update>
我们把拼接后的SQL打印出来,会发现一个问题。SQL中,分号(;
)表示一条语句的结束,使用上面的方式拼接出来的方式,是多条SQL。
因此产生了一个问题,Mybatis中一个Statement标签中可以有多条SQL吗?
答案是默认不可以,所以上面的代码报错了。
需要在数据库连接后面加上&allowMultiQueries=true
配置,如下:
再次执行,修改成功了,这是第一种方式;
查看日志发现,Updates:1,就是说如果需要返回更新的记录条数,那么这种方式返回的更新条数会是1,不能体现出数据库真实发生变化的记录条数;
另外,将多条SQL合成一条执行,有SQL注入的风险
方式二
第二种方式是用一条SQL的方式来实现,如下:
<update id="updateUser"> update tb_user set username = case <foreach collection="users" item="user"> when id = #{user.id} <choose> <when test="user.username != null and user.username != ''">then #{user.username}</when> <otherwise>then username</otherwise> </choose> </foreach> end, password = case <foreach collection="users" item="user"> when id = #{user.id} <choose> <when test="user.password != null and user.password != ''">then #{user.password}</when> <otherwise>then password</otherwise> </choose> </foreach> end where <foreach collection="users" item="user" separator="or"> id = #{user.id} </foreach> </update>
看着有些复杂,拼接后的SQL如下:
update tb_user set username = case when id = '1' then 'zhangsan_fix' when id = '2' then 'lisi_fix' end, password = case when id = '1' then password when id = '2' then '654321_fix' end where id = '1' or id = '2';
这种方式不需要加额外的配置,执行测试;
查看数据库,没得问题,批量修改完成了;
总结
本文介绍了Mybatis框架下,批量更新对象的两种方法:
- 方法一:将多条更新语句合成一条执行,需要在数据库链接后面增加配置,不能体现真实修改的记录条数,有SQL注入的风险;
- 方法二:使用case then 关键字实现,SQL复杂,行数多,降低了可阅读性;
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。