开发者

Mybatis批量更新对象数据的两种实现方式

开发者 https://www.devze.com 2024-08-10 14:20 出处:网络 作者: 何中应
目录创建Demo批量更新方式一方式二总结说明: 遇到一次需要批量修改对象的场景。
目录
  • 创建Demo
  • 批量更新
    • 方式一
    • 方式二
  • 总结

    说明:

    遇到一次需要批量修改对象的场景。

    传递一个对象集合,需要根据对象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
    @RequestMappiwww.devze.comng("/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("/upYxXnFWdateUser")
        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");
            uspythoner2.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';

    这种方式不需要加额外的配置,执行测试;

    javascript

    Mybatis批量更新对象数据的两种实现方式

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

    Mybatis批量更新对象数据的两种实现方式

    总结

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

    • 方法一:将多条更新语句合成一条执行,需要在数据库链接后面增加配置,不能体现真实修改的记录条数,有SQL注YxXnFW入的风险;
    • 方法二:使用case then 关键字实现,SQL复杂,行数多,降低了可阅读性;

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号