【SpringBoot DB系列】Jooq批量写入采坑记录

后面介绍了jooq的三种批量插入方式,后果最近发现这外面竟然还有一个深坑,我认为的批量插入竟然不是一次插入多条数据,而是一条一条的插入...,这就有点尬了

<!-- more -->

1. 三种插入姿态

对于我的项目创立以及jooq的相干应用姿态,举荐查看之前的博文: 【DB系列】Jooq之新增记录应用姿态

上面是咱们采纳的三种批量插入方式

/** * 通过Record执行批量增加 * * 通过源码查看,这种插入方式实际上是单条单条的写入数据,和上面的一次插入多条有本质区别 * * @param list * @return */public boolean batchSave(List<PoetBO> list) {    List<PoetPO> poList = list.stream().map(this::bo2po).collect(Collectors.toList());    int[] ans = dsl.batchInsert(poList).execute();    System.out.println(JSON.toJSONString(ans));    return true;}/** * 类sql写法,批量增加 * * @param list * @return */public boolean batchSave2(List<PoetBO> list) {    InsertValuesStep2<PoetPO, Integer, String> step = dsl.insertInto(table).columns(table.ID, table.NAME);    for (PoetBO bo : list) {        step.values(bo.getId(), bo.getName());    }    return step.execute() > 0;}/** * 不基于主动生成的代码,来批量增加数据 * * @param list * @return */public boolean batchSave3(List<PoetBO> list) {    InsertQuery insertQuery = dsl.insertQuery(DSL.table("poet"));    for (PoetBO bo : list) {        insertQuery.addValue(DSL.field("id", Integer.class), bo.getId());        insertQuery.addValue(DSL.field("name", String.class), bo.getName());        insertQuery.newRecord();    }    return insertQuery.execute() > 0;}

请留神下面的三种批量插入方式,基本上对应的就是jooq的三种常见的用法

  • 间接借助主动生成的Record类来操作
  • 类sql的拼接写法,基本上咱们平时的sql怎么写,这里就怎么用
  • InsertQuery:借助jooq提供的各种Query类来执行指标操作

2. 日志验证

下面三种写法中,第一种批量插入方式,并不是咱们传统了解的一次插入多条记录,相同它是一条一条的插入的,咱们能够通过开启jooq的日志来查看一些执行的sql状况

配置文件 application.properties,增加上面的配置

debug=falsetrace=falselogging.level.org.jooq=DEBUG

如果有本人的logback.xml配置文件,能够调整一下日志级别,将jooq的debug日志放进去

一个简略的测试case

public void test() {  this.batchSave(Arrays.asList(new PoetBO(14, "yh"), new PoetBO(15, "yhh")));  this.batchSave2(Arrays.asList(new PoetBO(16, "yihui"), new PoetBO(17, "yihuihui")));  this.batchSave3(Arrays.asList(new PoetBO(18, "YiHui"), new PoetBO(19, "YiHuiBlog")));}

从下面的sql来看,前面两个的确是一次插入多条,然而第一个,也没有将具体执行的sql打印进去,所有不看源码的话,也没有方法实锤是一条一条插入的

为了验证这个问题,一个简略的解决办法就是批量插入两条数据,第一条失常,第二条异样,如果第一条插入胜利,第二条失败那就大概率是单个插入的了

// 表构造中,name的字段最大为20,上面插入的第二条数据长度超限try {    this.batchSave(Arrays.asList(new PoetBO(14, "yh"), new PoetBO(15, "1234567890098765432112345")));} catch (Exception e) {    e.printStackTrace();}try {    this.batchSave2(Arrays.asList(new PoetBO(16, "yihui"), new PoetBO(17, "1234567890098765432112345")));} catch (Exception e) {    e.printStackTrace();}this.batchSave3(Arrays.asList(new PoetBO(18, "YiHui"), new PoetBO(19, "YiHuiBlog")));

第一种批量插入失败

第二种插入失败

插入后后果

请留神下面的报错,以及最终插入的后果,第一种插入方式一个插入胜利一个失败;第二种批量插入方式,两条都插入失败;

通常状况下,一次插入多条数据时,一个插入失败,会导致整个插入都失败,如下

3. 源码剖析

下面是从日志以及后果体现来揣测理论的执行状况,接下来就须要从源码角度来看一下,是否真的是单个的执行了

省略掉具体的定位过程,间接找到org.jooq.impl.BatchCRUD#execute,对应的代码

@Overridepublic final int[] execute() throws DataAccessException {    // [#1180] Run batch queries with BatchMultiple, if no bind variables    // should be used...    if (executeStaticStatements(configuration.settings())) {        return executeStatic();    }    else {        return executePrepared();    }}

下面有两种插入方式,对于插入的外围逻辑一样

遍历汇合,获取单个 record,执行 CURD

II. 其余

0. 我的项目

系列博文

  • 【SpringBoot DB系列】Jooq之记录更新与删除
  • 【SpringBoot DB系列】Jooq之新增记录应用姿态
  • 【SpringBoot DB系列】Jooq代码主动生成
  • 【SpringBoot DB系列】Jooq初体验

我的项目源码

  • 工程:https://github.com/liuyueyi/spring-boot-demo
  • 我的项目源码: https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/108-jooq-curd

1. 一灰灰Blog

尽信书则不如,以上内容,纯属一家之言,因集体能力无限,不免有疏漏和谬误之处,如发现bug或者有更好的倡议,欢送批评指正,不吝感谢

上面一灰灰的集体博客,记录所有学习和工作中的博文,欢送大家前去逛逛

  • 一灰灰Blog集体博客 https://blog.hhui.top
  • 一灰灰Blog-Spring专题博客 http://spring.hhui.top