Mybatis批量操作


文章目录

  • Mybatis批量操作
  • 1 数据库结构
  • 2 JDBC配置及Mapper映射配置
  • 3 实体类
  • 4 持久层类
  • 5 映射文件
  • 6 测试方法
  • 7 总结




1 数据库结构

mybatisplus mysql 保存geometry mybatis保存或更新数据_SQL

2 JDBC配置及Mapper映射配置

项目结构如下:

mybatisplus mysql 保存geometry mybatis保存或更新数据_foreach_02

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

注意:

  • url需要添加allowMultiQueries=true参数,允许批量操作,具体详情,参考这篇文章:
  • Jdbc Url 设置allowMultiQueries为true和false时底层处理机制研究
  • 我的MySQL版本是8,所以还需要加serverTimezone=GMT%2B8

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标签的属性,可以参考以下博客:
  • MyBatis:SQL语句中的foreach标签的详细介绍
  • MyBatis动态sql之foreach标签
  • item表示集合中迭代的对象
  • index表示迭代到的位置
  • open表示该语句以什么开始
  • separator表示每次迭代之间的分隔符
  • close表示以什么结束
  • 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);
    }

mybatisplus mysql 保存geometry mybatis保存或更新数据_foreach_03

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

@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,效果如下:

mybatisplus mysql 保存geometry mybatis保存或更新数据_foreach_04

7 总结

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