在日常开发中,批量添加数据是高频需求 —— 比起单条循环插入,批量添加能大幅减少数据库交互次数,提升数据插入效率。MyBatis 通过动态 SQL 的<foreach>标签,就能轻松实现批量插入功能。本文结合实战场景,从核心原理到具体实现,一步步教你掌握 MyBatis 批量添加的全流程,新手也能快速上手。

一、批量添加的核心逻辑

MyBatis 批量添加的本质是将多条插入语句合并为单条多值 SQL,语法格式如下:

INSERT INTO user (name, age, email) 
VALUES (值1, 值2, 值3), (值4, 值5, 值6), (值7, 值8, 值9);

核心关键有两点:

  1. 入参类型:用List集合包裹实体对象(如List<User>),统一传递多条数据;
  2. 动态 SQL:通过<foreach>标签遍历集合,自动生成多个(值列表),并用逗号分隔。

对比单条插入,批量添加能减少 SQL 解析次数和网络通信开销,数据量越大,性能优势越明显。

二、实战准备:实体类规范

首先需确保实体类符合 MyBatis 映射要求,避免因配置不当导致数据插入失败:

import java.io.Serializable;

public class User implements Serializable {

    private static final long serialVersionUID = 1L;
    
    private Integer id;
    private String name;
    private Integer age;
    private String email;

    public User() {}

    public User(String name, Integer age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
    }


    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public Integer getAge() { return age; }
    public void setAge(Integer age) { this.age = age; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

2. 核心注意点

  • 主键id自增时,插入语句中需排除该字段,避免手动赋值覆盖自增逻辑;
  • 必须同时提供无参和带参构造器:无参构造器供 MyBatis 实例化,带参构造器方便快速创建对象;
  • 字段使用包装类(如Integer而非int),避免 null 值无法表达的问题。

三、核心实现:Mapper 接口 + 动态 SQL

1. Mapper 接口定义

批量添加的入参为List<User>,需通过@Param注解指定集合别名(便于 XML 中引用):

import org.apache.ibatis.annotations.Param;
import java.util.List;

public interface UserMapper {
    // 单条插入
    int insertUser(User user);

    // 批量插入
    int batchInsertUsers(@Param("users") List<User> users);
}

2. XML 动态 SQL 编写

核心是通过<foreach>标签遍历集合,生成多值插入语句,注意避免多余括号嵌套:

<?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.example.mapper.UserMapper">

    <insert id="batchInsertUsers" parameterType="java.util.List">
        INSERT INTO user (name, age, email)
        VALUES
        <foreach collection="users" 
                 item="user"        
                 separator=",">     
            (#{user.name}, #{user.age}, #{user.email})
        </foreach>
    </insert>

    <insert id="insertUser" parameterType="com.example.pojo.User">
        INSERT INTO user (name, age, email)
        VALUES (#{name}, #{age}, #{email})
    </insert>
</mapper>

四、测试验证:批量插入实战

编写测试类,创建多个 User 对象并批量插入,注意添加事务注解保证数据提交:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring-mybatis.xml")
public class UserMapperTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    @Transactional  
    public void testBatchInsertUsers() {
        User user1 = new User("张三", 20, "zhangsan@test.com");
        User user2 = new User("李四", 22, "lisi@test.com");
        User user3 = new User("王五", 25, "wangwu@test.com");

        List<User> userList = new ArrayList<>();
        userList.add(user1);
        userList.add(user2);
        userList.add(user3);

        int rows = userMapper.batchInsertUsers(userList);
        System.out.println("批量插入成功,影响行数:" + rows);
    }
}

2. 测试结果验证

运行测试后,查询数据库user表,会发现 3 条数据已同时插入,主键 id 自动生成,证明批量添加功能生效。

五、生产级注意事项

  1. 事务控制:批量插入必须加@Transactional注解,避免部分数据插入成功、部分失败导致数据不一致;
  2. 数据量控制:单次批量插入不宜超过 1000 条,数据量过大时可分批次插入(如每 500 条提交一次),避免 SQL 过长或事务过大;
  3. 数据库兼容:本文语法适用于 MySQL,Oracle 需改用INSERT ALL语法(如INSERT ALL INTO user VALUES(...) INTO user VALUES(...) SELECT 1 FROM DUAL);
  4. 性能优化:MySQL 连接 URL 添加rewriteBatchedStatements=true,开启 JDBC 批量优化,进一步提升插入效率;
  5. 参数校验:批量插入前需校验集合非空、元素字段非空,避免因单条数据非法导致整批插入失败。

六、总结

MyBatis 批量添加的核心是「List入参 +<foreach>动态 SQL」,步骤简单但需注意细节:

  1. 实体类需满足无参构造器、序列化等规范;
  2. XML 中<foreach>标签需正确配置集合别名和分隔符,避免括号嵌套错误;
  3. 测试和生产环境需开启事务,控制批量数据量。

掌握这套方法后,无论是日常批量导入数据,还是高并发场景下的数据批量存储,都能高效应对。相比单条插入,批量添加能减少 90% 以上的数据库交互开销,是提升系统性能的关键技巧之一。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐