关于springboot:SpringBoot-DB系列Jooq批量写入采坑记录

45次阅读

共计 3170 个字符,预计需要花费 8 分钟才能阅读完成。

【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=false
trace=false
logging.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,对应的代码

@Override
public 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

正文完
 0