MyBatis批量插入详解(3种主流批量新增操作)

MyBatis批量插入详解(3种主流批量新增操作)-mikechen

使用Mybatis框架批量插入的3种方法:多次调用insert方法、foreach标签、batch模式,下面分别详解@mikechen

多次调用insert插入

这种方式理解起来最简单,一个单独的插入接口,业务上循环调用即可。

1.增加Mapper接口

@Mapper
public interface InsertMapper {
    /**
     * 写入
     * @param po
     * @return
     */
    int save(@Param("po") MoneyPo po);
}

2.对应XML配置

<resultMap id="BaseResultMap" type="com.mikechen.mybatis.entity.UserPo">
    <id column="id" property="id" jdbcType="INTEGER"/>
    <result column="name" property="name" jdbcType="VARCHAR"/>
    <result column="money" property="money" jdbcType="INTEGER"/>
    <result column="is_deleted" property="isDeleted" jdbcType="TINYINT"/>
    <result column="create_at" property="createAt" jdbcType="TIMESTAMP"/>
    <result column="update_at" property="updateAt" jdbcType="TIMESTAMP"/>
</resultMap>
<insert id="save" parameterType="com.mikechen.mybatis.entity.MoneyPo" useGeneratedKeys="true" keyProperty="po.id">
  INSERT INTO `user` (`name`, `money`, `is_deleted`)
  VALUES
(#{po.name}, #{po.money}, #{po.isDeleted});
</insert>

 

3.业务逻辑代码

private UserPo buildPo() {
    UserPO po = new UserPo();
    po.setName("mikechen");
    po.setMoney((long) random.nextInt(12343));
    po.setIsDeleted(0);
    return po;
}


public void testBatchInsert() {
    for (int i = 0; i < 10; i++) {
        moneyInsertMapper.save(buildPo());
    }
}

这种方式的优点就是简单直观,缺点就是db交互次数多,开销大。

 

foreach插入

这种方法是依靠 MyBatis 中的 foreach 标签,将数据拼接成一条原生的 insert 语句一次性执行的。

1.增加插入接口

@Mapper
public interface UserMapper extends BaseMapper<User> {

    boolean saveBatchByNative(List<User> list);
}

 

2.创建UserMapper.xml 文件

使用 foreach 标签拼接 SQL,如下所示:

<?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.demo.mapper.UserMapper">
    <insert id="saveBatchByNative">
        INSERT INTO `USER`(`NAME`,`PASSWORD`) VALUES
        <foreach collection="list" separator="," item="item">
            (#{item.name},#{item.password})
        </foreach>
    </insert>

</mapper>

 

3.业务逻辑实现

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Autowired
    private UserMapper userMapper;

    public boolean saveBatchByNative(List<User> list) {
        return userMapper.saveBatchByNative(list);
    }

}

使用sql批量插入的方式,优点是db交互次数少,在插入数量可控时,相比于前者开销更小。

缺点也很明显,当一次插入的数量太多时,组装的sql既有可能直接超过了db的限制无法执行了。

 

batch模式插入

针对上面做一个简单的优化,使用BATCH批处理模式,实现会话复用,避免每次请求都重新维护一个链接导致额外开销。

使用如下:

@Autowired
    private SqlSessionFactory sqlSessionFactory;
    //通过Mybatis batch模式批量插入群组人员
    //开启BATCH批量模式
    SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
    TIdReGroupUserMapper tIdReGroupUserMapper = sqlSession.getMapper(TIdReGroupUserMapper.class);
    int addNum = 0;
    try {
            TIdReGroupUser tIdReGroupUser = new TIdReGroupUser();
            for (int i = 0; i < userIds.length; i++) {
                tIdReGroupUser.setId(UUID.randomUUID().toString());
                tIdReGroupUser.setGroupId(groupId);
                tIdReGroupUser.setUserId(userIds[i]);
                addNum += tIdReGroupUserMapper.insert(tIdReGroupUser);
            }
            sqlSession.commit();
        }finally {
            closeSqlSession(sqlSession, sqlSessionFactory);
        }
}

使用Mybatis的batch模式进行批量插入,数据量较大的场景中后者效率更高。

 

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法