欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MyBatis批量更新和保存

程序员文章站 2022-05-25 15:43:01
...

Mybatis批量操作



1 数据库结构

MyBatis批量更新和保存

2 JDBC配置及Mapper映射配置

项目结构如下:

MyBatis批量更新和保存

yml文件:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/example?allowMultiQueries=true&serverTimezone=GMT%2B8
    username: root
    password: root

mybatis:
  type-aliases-package: com.iotat.weather.pojo
  mapper-locations: classpath:mapper/*.xml

注意:

3 实体类

public class User {
    private Integer id;
    private String userName;
    private String password;
	//以下省略toString()方法和setter、getter方法
}

4 持久层类

@Mapper
@Repository
public interface UserMapper {

    List<User> findAll();

    void saveUser(List<User> users);

    void updateUser(List<User> users);

}

5 映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.jk.login.mapper.UserMapper">

    <!--结果集映射-->
    <resultMap id="userMap" type="User">
        <result column="id" property="id"/>
        <result column="u_name" property="userName"/>
        <result column="u_psw" property="password"/>
    </resultMap>

    <select id="findAll" resultMap="userMap">
        select * from tb_user
    </select>

    <insert id="saveUser" parameterType="java.util.List">
        insert into tb_user(u_name,u_psw) values
        <foreach collection="list" index="index" item="item" separator=",">
            (#{item.userName},#{item.password})
        </foreach>
    </insert>

    <update id="updateUser" parameterType="java.util.List">
        <foreach collection="list" index="index" item="item" separator=";">
            update tb_user set u_psw = #{item.password} where u_name = #{item.userName}
        </foreach>
    </update>

</mapper>

注意:

  • 关于foreach标签的属性,可以参考以下博客:

  • foreach标签的实质是拼接SQL语句,我们需要重点关注的是collection标签和separator,前者表示需要迭代对象的类型,后者表示每次迭代之间的分割符号。

  • 在这里我的insert标签循环拼接的是values后面的语句,最终的拼接结果如下:

insert into tb_user(u_name,u_psw) values
(userName1,password1),
(userName2,password2),
(userName3,password3),
...

如上所示,在insert标签中循环拼接的结果是一条SQL语句,所以用逗号作为分隔符,分隔每个value值。

  • 在这里我的update标签循环的是整条SQL语句,最终的循环结果如下:
update tb_user set u_psw = password1 where u_name = userName1;
update tb_user set u_psw = password2 where u_name = userName2;
update tb_user set u_psw = password3 where u_name = userName3;
...

如上所示,在update标签中循环拼接的结果是多条SQL语句,所以用分号隔开,分隔每条SQL语句。而且还需要在jdbc配置URL连接处添加allowMultiQueries=true参数,否则就算语法是正确的,程序也会报错,是一个小坑。

6 测试方法

    @Autowired
    UserMapper userMapper;
    
    @Test
    void testSave() {
        List<User> list = new ArrayList<>();

        User user1 = new User();
        user1.setUserName("admin");
        user1.setPassword("111");

        User user2 = new User();
        user2.setUserName("normal");
        user2.setPassword("222");

        User user3 = new User();
        user3.setUserName("general");
        user3.setPassword("333");
        
        list.add(user1);
        list.add(user2);
        list.add(user3);
        userMapper.saveUser(list);
    }

MyBatis批量更新和保存

可以看到,批量插入成功了,下面测试批量更新。

    @Test
    void testUpdate(){
        List<User> list = userMapper.findAll();
        List<User> newList = new ArrayList<>();
        for (User u : list){
            u.setPassword("111111");
            newList.add(u);
        }
        userMapper.updateUser(newList);
    }

上面代码是将所有账户的密码都设置成6个1,效果如下:

MyBatis批量更新和保存

7 总结

  • 采坑1:url连接处需要设置allowMultiQueries=true,允许批量操作。
  • 采坑2:foreach标签的separator属性需根据实际的SQL语句决定。
  • 采坑3:不熟悉SQL语法,在写原生SQL的时候先去数据库里测试语法是否正确。