溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何使用Mybatis的Batch?Insert?Support實(shí)現(xiàn)批量插入

發(fā)布時(shí)間:2022-07-11 09:28:24 來(lái)源:億速云 閱讀:863 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹了如何使用Mybatis的Batch Insert Support實(shí)現(xiàn)批量插入的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇如何使用Mybatis的Batch Insert Support實(shí)現(xiàn)批量插入文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。

Batch Insert Support 批量插入

在開(kāi)發(fā)中如果遇到需要批量insert的需求,可以使用Mybatis 的 Batch Insert Support 提高插入效率。

代碼實(shí)例(開(kāi)發(fā)的項(xiàng)目中截取的片段)

@Autowired
private SqlSessionTemplate sqlSessionTemplate;
public int insertFolder(List<IpsCatalogFolderDetail> ips) {
        //獲取sql會(huì)話
        SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
        //通過(guò)新的session獲取mapper,而不是常規(guī)的spring管理注入
        IipsCatalogFolderDetailDao folderDetailDao = session.getMapper(IipsCatalogFolderDetailDao.class);
        int size = ips.size();
        //如果有父類子類兩層都需要批量插入也可
        try {
        //外層循環(huán)
            for (int i = 0; i < size; i++) {
                    ips.get(i).setType("folder");
                    //用上面在session中獲取的mapper進(jìn)行插入操作
                    folderDetailDao.insertFolder(ips.get(i));
                //內(nèi)層循環(huán)
                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進(jìn)行插入操作
                                folderDetailDao.insertFolder(ifd);
                        }
                    }
                }
                //最后批量提交
                    if (i % 200 == 0 || i == size - 1) {
                        session.commit();//200個(gè)提交一次,手動(dòng)提交,提交后無(wú)法回滾
                        session.clearCache(); //清理緩存,防止溢出
                    }
            }
        }catch (Exception e) {
            System.out.println(e.toString());
           session.rollback(); //沒(méi)有提交的數(shù)據(jù)可以回滾
        } finally {
            session.close();
        }
        return 0;
    }

另外有時(shí)我們?cè)诓迦氲臅r(shí)候需要先查詢數(shù)據(jù)是否已存在,如果也需要批量操作可將insert和update語(yǔ)句合并,然后就可以繼續(xù)使用Batch Insert了

ORACLE數(shù)據(jù)庫(kù)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);

批量插入幾千條數(shù)據(jù)優(yōu)化(foreach)

項(xiàng)目中有一個(gè)耗時(shí)較長(zhǎng)的Job存在CPU占用過(guò)高的問(wèn)題

經(jīng)排查發(fā)現(xiàn),主要時(shí)間消耗在往MyBatis中批量插入數(shù)據(jù)。mapper configuration是用foreach循環(huán)做的,差不多是這樣。

<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>

優(yōu)化代碼

可以看 http://www.mybatis.org/mybatis-dynamic-sql/docs/insert.html 中 Batch Insert Support 標(biāo)題里的內(nèi)容)

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();
}

總結(jié)一下,如果MyBatis需要進(jìn)行批量插入,推薦使用 ExecutorType.BATCH 的插入方式,如果非要使用 <foreach>的插入的話,需要將每次插入的記錄控制在 20~50 左右

關(guān)于“如何使用Mybatis的Batch Insert Support實(shí)現(xiàn)批量插入”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“如何使用Mybatis的Batch Insert Support實(shí)現(xiàn)批量插入”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI