Mybatis批量更新对象数据的两种方法
  KRe60ogUm4le 12天前 14 0

说明:遇到一次需要批量修改对象的场景。传递一个对象集合,需要根据对象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

Mybatis批量更新对象数据的两种方法

项目启动,测试一下接口,没得问题;

Mybatis批量更新对象数据的两种方法

批量更新

创建一个新的接口,用于触发批量更新对象的代码,内容是传递一个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批量更新对象数据的两种方法

因此产生了一个问题,Mybatis中一个Statement标签中可以有多条SQL吗? 答案是默认不可以,所以上面的代码报错了。需要在数据库连接后面加上&allowMultiQueries=true配置,如下:

Mybatis批量更新对象数据的两种方法

再次执行,修改成功了,这是第一种方式;

Mybatis批量更新对象数据的两种方法

Mybatis批量更新对象数据的两种方法

查看日志发现,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批量更新对象数据的两种方法

查看数据库,没得问题,批量修改完成了;

Mybatis批量更新对象数据的两种方法

总结

本文介绍了Mybatis框架下,批量更新对象的两种方法:

  • 方法一:将多条更新语句合成一条执行,需要在数据库链接后面增加配置,不能体现真实修改的记录条数,有SQL注入的风险;

  • 方法二:使用case then 关键字实现,SQL复杂,行数多,降低了可阅读性;

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 12天前 0

暂无评论

推荐阅读
  ltERVYe6WHLK   2023年12月05日   15   0   0 javajava
  b9hKhDfaazC9   2023年11月30日   17   0   0 javaHadoopjavaHadoop
  KRe60ogUm4le   5天前   15   0   0 javascala
  F5MM6ELZe4VV   2023年11月28日   15   0   0 hivejavahiveJava
KRe60ogUm4le