使用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面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》