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复杂,行数多,降低了可阅读性;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何中应

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值