使用Mybatis的Batch Insert Support 实现批量插入

目录
  • Batch Insert Support 批量插入
    • 代码实例(开发的项目中截取的片段)
    • ORACLE数据库sql示例
  • 批量插入几千条数据优化(foreach)
    • 项目中有一个耗时较长的Job存在CPU占用过高的问题
    • 优化代码

Batch Insert Support 批量插入

在开发中如果遇到需要批量insert的需求,可以使用Mybatis 的 Batch Insert Support 提高插入效率。

代码实例(开发的项目中截取的片段)

@Autowired
private SqlSessionTemplate sqlSessionTemplate;
public int insertFolder(List<IpsCatalogFolderDetail> ips) {
        //获取sql会话
        SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
        //通过新的session获取mapper,而不是常规的spring管理注入
        IipsCatalogFolderDetailDao folderDetailDao = session.getMapper(IipsCatalogFolderDetailDao.class);
        int size = ips.size();
        //如果有父类子类两层都需要批量插入也可
        try {
        //外层循环
            for (int i = 0; i < size; i++) {
                    ips.get(i).setType("folder");
                    //用上面在session中获取的mapper进行插入操作
                    folderDetailDao.insertFolder(ips.get(i));
                //内层循环
                String cs = ips.get(i).getContentIds();
                if (StringUtils.isNotBlank(cs)){
                        List<String> con = JSON.parseArray(cs,String.class);
                    if (cs != null && con.size() > 0) {
                        for (int j = 0; j < con.size(); j++) {
                                IpsCatalogFolderDetail ifd = new IpsCatalogFolderDetail();
                                ifd.setParentCode(ips.get(i).getCode());
                                ifd.setContentId(con.get(j));
                                ifd.setType("contents");
                                 //同样用上面在session中获取的mapper进行插入操作
                                folderDetailDao.insertFolder(ifd);
                        }
                    }
                }
                //最后批量提交
                    if (i % 200 == 0 || i == size - 1) {
                        session.commit();//200个提交一次,手动提交,提交后无法回滚
                        session.clearCache(); //清理缓存,防止溢出
                    }
            }
        }catch (Exception e) {
            System.out.println(e.toString());
           session.rollback(); //没有提交的数据可以回滚
        } finally {
            session.close();
        }
        return 0;
    }

另外有时我们在插入的时候需要先查询数据是否已存在,如果也需要批量操作可将insert和update语句合并,然后就可以继续使用Batch Insert了

ORACLE数据库sql示例

@Insert("merge into ips_catalog_folder_detail fd " +
            "using(select #{code,jdbcType=VARCHAR} c from dual)t " +
            "on(fd.FOLDERID = t.c)" +
            
            "when matched then"+
            "update set "+
            ...(省略)...
            "where ..."+
            "when not matched then insert(" +
            "fd.PROD_LINE," +
            "fd.TYPE," +
            "fd.PARENTFOLDERCODE," +
            "fd.FOLDERID," +
            "fd.FOLDERCODE," +
            "fd.FOLDERNAME," +
            "fd.COLUMN_SORTINDEX," +
            "fd.DESCRIPTION," +
            "fd.CONTENTID," +
            "fd.CREATETIME" +
            ")" +
            "VALUES" +
            "(" +
            "#{prod_line}," +
            "#{type,jdbcType=VARCHAR}," +
            "#{parentCode,jdbcType=VARCHAR}," +
            "#{code,jdbcType=VARCHAR}," +
            "#{aliasCode,jdbcType=VARCHAR}," +
            "#{name,jdbcType=VARCHAR}," +
            "#{sortIndex,jdbcType=VARCHAR}," +
            "#{desc,jdbcType=VARCHAR}," +
            "#{contentId,jdbcType=VARCHAR}," +
            "#{createTime,jdbcType=VARCHAR}" +
            ")")
            int insertFolder(IpsCatalogFolderDetail fd);

MYSQL示例:

REPLACE INTO users (id,name,age) VALUES(1, '张雨绮', 32); 

批量插入几千条数据优化(foreach)

项目中有一个耗时较长的Job存在CPU占用过高的问题

经排查发现,主要时间消耗在往MyBatis中批量插入数据。mapper configuration是用foreach循环做的,差不多是这样。

<insert id="batchInsert" parameterType="java.util.List">
    insert into USER (id, name) values
    <foreach collection="list" item="model" index="index" separator=","> 
        (#{model.id}, #{model.name})
    </foreach>
</insert>

优化代码

可以看 http://www.mybatis.org/mybatis-dynamic-sql/docs/insert.html 中 Batch Insert Support 标题里的内容)

SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
    SimpleTableMapper mapper = session.getMapper(SimpleTableMapper.class);
    List<SimpleTableRecord> records = getRecordsToInsert(); // not shown
 
    BatchInsert<SimpleTableRecord> batchInsert = insert(records)
            .into(simpleTable)
            .map(id).toProperty("id")
            .map(firstName).toProperty("firstName")
            .map(lastName).toProperty("lastName")
            .map(birthDate).toProperty("birthDate")
            .map(employed).toProperty("employed")
            .map(occupation).toProperty("occupation")
            .build()
            .render(RenderingStrategy.MYBATIS3);
 
    batchInsert.insertStatements().stream().forEach(mapper::insert);
    session.commit();
} finally {
    session.close();
}

总结一下,如果MyBatis需要进行批量插入,推荐使用 ExecutorType.BATCH 的插入方式,如果非要使用 <foreach>的插入的话,需要将每次插入的记录控制在 20~50 左右

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Mybatis三种批量插入数据的方式

    1. 循环插入 mapper.xml: <?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.buhe.

  • mybatis中批量插入的两种方式(高效插入)

    MyBatis简介 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 一.mybiats foreach标签 foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合.foreach元素的属性主

  • 解决Mybatis 大数据量的批量insert问题

    前言 通过Mybatis做7000+数据量的批量插入的时候报错了,error log如下: , ('G61010352', '610103199208291214', '学生52', 'G61010350', '610103199109920192', '学生50', '07', '01', '0104', ' ', , ' ', ' ', current_timestamp, current_timestamp ) 被中止,呼叫 getNextException 以取得原因. at org.p

  • 使用Mybatis的Batch Insert Support 实现批量插入

    目录 Batch Insert Support 批量插入 代码实例(开发的项目中截取的片段) ORACLE数据库sql示例 批量插入几千条数据优化(foreach) 项目中有一个耗时较长的Job存在CPU占用过高的问题 优化代码 Batch Insert Support 批量插入 在开发中如果遇到需要批量insert的需求,可以使用Mybatis 的 Batch Insert Support 提高插入效率. 代码实例(开发的项目中截取的片段) @Autowired private SqlSess

  • MyBatis动态SQL foreach标签实现批量插入的方法示例

    需求:查出给定id的记录: <select id="getEmpsByConditionForeach" resultType="comtestbeansEmployee"> SELECT * FROM tb1_emplyee WHERE id IN <foreach collection="list" item="item_id" separator="," open="(&q

  • Mybatis 插入一条或批量插入 返回带有自增长主键记录的实例

    首先讲一下, 插入一条记录返回主键的 Mybatis 版本要求低点,而批量插入返回带主键的 需要升级到3.3.1版本,3.3.0之前的都不行. <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>3.3.1</version> </dependency> 1.MySQL <

  • MyBatis 实现批量插入和删除中双层循环的写法案例

    本博客主要用两个例子来说明一下批量删除和批量插入双层循环的用法,顺便自己记录一下,方便以后使用. 1.批量删除 (1):dao中的写法: public int batchDelPrice(@Param("deleteList")List<Map<String, Object>> deleteList); 其中deleteList是一个Map的集合,Map中的Object是一个list集合,deleteList拼接如下: List<String> de

  • MySQL和Oracle批量插入SQL的通用写法示例

    目录 举个例子: 通用写法: 总结 举个例子: 现在要批量新增User对象到数据库USER表中 public class User{ //姓名 private String name; //年龄 private Integer age; //性别 private Integer sex } 大部分人对MySQL比较熟悉,可能觉得批量新增的SQL都是这样写,其实并不然.该写法在MySQL中没问题,而在Oracle中,这样写就会报错. MySQL写法: INSERT INTO USER (NAME,

  • MyBatis通过BATCH批量提交的方法

    很多人在用 MyBatis 或者 通用 Mapper 时,经常会问有没有批量插入和批量更新的方法. 实际上许多时候没必要用<foreach> 去实现特别复杂的批量操作.直接通过 MyBatis 的 BATCH 方式执行增删改方法即可. 下面是一个批量用法的例子: @Autowired private SqlSessionFactory sqlSessionFactory; @Transactional(rollbackFor = Exception.class) @Override publi

  • Oracle+Mybatis的foreach insert批量插入报错的快速解决办法

    最近做一个批量导入的需求,将多条记录批量插入数据库中. 解决思路:在程序中封装一个List集合对象,然后把该集合中的实体插入到数据库中,因为项目使用了MyBatis,所以打算使用MyBatis的foreach功能进行批量插入.期间遇到了"SQL 命令未正确结束 "的错误,最终解决,记录下来供以后查阅和学习. 首先,在网上参考了有关Mybatis的foreach insert的资料,具体如下: foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合. foreach

  • MyBatis批量插入(insert)数据操作

    在程序中封装了一个List集合对象,然后需要把该集合中的实体插入到数据库中,由于项目使用了Spring+MyBatis的配置,所以打算使用MyBatis批量插入,由于之前没用过批量插入,在网上找了一些资料后最终实现了,把详细过程贴出来. 实体类TrainRecord结构如下: public class TrainRecord implements Serializable { private static final long serialVersionUID = -12069604621179

  • Oracle + Mybatis实现批量插入、更新和删除示例代码

    前言 Mybatis是web工程开发中非常常用的数据持久化的框架,通过该框架,我们非常容易的进行数据库的增删改查.数据库连接进行事务提交的时候,需要耗费的资源比较多,如果需要插入更新的数据比较多,而且每次事务只提交一条数据,会造成非常大的数据库资源浪费,导致数据库性能.系统性能大幅度下降. 关于mybatis的批量插入,网上的多数示例多半是关于MySQL数据库的,关于Oracle数据库的例子比较少.本文将给大家介绍关于Oracle+Mybatis批量插入.更新和删除的相关内容,下面话不多说了,来

随机推荐