【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