Mybatis批量插入3种方式

举报
LoneWalker、 发表于 2023/08/31 09:18:34 2023/08/31
【摘要】 Mybatis批量插入3种方式

 前言

数据库使用的mysql,jdk版本1.8,springboot环境,   需要注意的是我们测试的单条sql比较短

max_allowed_packet指代mysql服务器端和客户端在一次传送数据包的过程当中最大允许的数据包大小。这里是4M

编辑

对比以下三种方式:

  1. for循环执行单条插入语句
  2. xml拼接sql
  3. 批处理执行

代码

mapper

@Mapper
public interface UserMapper {

    int insert(User user);

    int insertByBatch(List<User> users);

    int delete();
}

xml

  <insert id="insert" parameterType="com.example.mybatisdemo.entity.User">
        insert into user (name,age) values(#{name},#{age})
    </insert>

    <insert id="insertByBatch" parameterType="java.util.List">
        insert into user (name,age) values
        <foreach collection="list" item="item" separator=",">
            (#{item.name},#{item.age})
        </foreach>
    </insert>

    <delete id="delete">
        delete from user
    </delete>

拼接方式需要注意如果使用的是Oracle 

<foreach collection="list" item="item"  separator ="UNION ALL">
</foreach>

测试类

@SpringBootTest
class MybatisdemoApplicationTests {

    @Autowired
    UserMapper userMapper;

    @Autowired
    SqlSessionFactory sqlSessionFactory;

    private List<User> users = new ArrayList<User>();

    @Test
    void delete(){
        userMapper.delete();
    }

    @Test
    void insert() {
        for (int i = 0; i < 1000; i++){
            User user = new User();
            user.setName("人物"+i);
            user.setAge(i);
            users.add(user);
        }
        long start = System.currentTimeMillis();
        users.forEach(userMapper::insert);
        System.out.println(System.currentTimeMillis() - start);
    }

    @Test
    void insertByBatch(){
        for (int i = 0; i < 1000; i++){
            User user = new User();
            user.setName("人物"+i);
            user.setAge(i);
            users.add(user);
        }
        long start = System.currentTimeMillis();
        userMapper.insertByBatch(users);
        System.out.println(System.currentTimeMillis() - start);
    }

    @Test
    void insertByOnce(){
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH,false);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        long start = 0L;
        try{
        for (int i = 0; i < 1000; i++){
            User user = new User();
            user.setName("人物"+i);
            user.setAge(i);
            start = System.currentTimeMillis();
            mapper.insert(user);
            if (i%1000 == 999){
                //每1000条提交一次防止内存溢出
                sqlSession.commit();
                sqlSession.clearCache();
            }
        }
        System.out.println(System.currentTimeMillis() - start);
        }catch (Exception e){
          //没有提交的数据进行回滚
          sqlSession.rollback();
      }finally{
         //关闭会话
         sqlSession.close();
      }
    }
}

对比

方式 50条 1000条 2000条 3000条
for循环 562ms 2577ms 4828ms 6144ms
xml拼接 479ms 582ms 618ms 655ms
批处理 75ms 1683ms 1790ms 1843ms




注意我们这里测试的单条sql较短,当xml拼接过长就会报以下错误

总结

循环插入单条数据  效率确实不好,但是代码量少,在需求插入数据量不大的情况也是可以使用的。

xml拼接sql方式   网上千篇一律的说任何时候都不要使用,但是我觉得在可控范围内,效率这么好为什么不使用呢,当然必须要注意上面报错的情况,还是根据实际情况而定。

批处理执行 有大量数据插入时推荐此方式。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。