不要忘记在jOOQ中调用.execute()

323 阅读2分钟

jOOQ的DSL,像任何流畅的API一样,有一个很大的注意事项。你很容易忘记调用.execute() 。而当你这样做的时候,你有可能会盯着你的代码好几分钟,因为一切看起来都很完美:

ctx.insertInto(T)
   .columns(T.A, T.B)
   .values(1, 2);

盯着...盯着...盯着...为什么没有插入那一行?

"啊呀,又来了!!"

这就是它的做法:

ctx.insertInto(T)
   .columns(T.A, T.B)
   .values(1, 2)
   .execute();

原则上,这种错误可能发生在任何流畅的API上。比如说。StringBuilder

sb.append("a").append("b"); // Not consuming the result

或者流:

Stream.of(1, 2).peek(System.out::println); // Not so much peeking

但通常不会发生那么多,因为与jOOQ的区别在于:

  • jOOQ的DML语句(INSERT,UPDATE,DELETE,MERGE )和DDL语句(CREATE,ALTER,DROP,TRUNCATE ),以及其他一些产生的副作用
  • 这个副作用是我们唯一关心的事情。其结果(更新次数)大部分是不相关的

因此,我们并不关心execute() 的结果,它是一个int 。没有人忘记在一个jOOQResultQuery 上调用fetch()

ctx.select(T.A, T.B)
   .from(T); // Well duh

因为如果不调用fetch() 或类似的东西,我们就不会得到任何结果,而我们想要这些结果,就像调用StringBuilderStream 。但我们不想要execute() 的结果。

因此,即使是我们,在编写jOOQ的集成测试时,偶尔也会忘记调用这个愚蠢的小方法。

再也不会了!

当它在本周再次发生时...

花了10分钟试图弄清楚为什么我的JOOQ插入似乎不工作了...

... 忘记了`.execute()`

... 该死的令人震惊的同事在这里

- 💀 r͍̣̼ͯ̑ͪ ̽ͦfͤ͐ĺ̫̺̙̃͐c͙̪̤̘̯ 💀 (@_fletchr)March 25, 2021

...我终于创建了一个问题来思考这个问题:https://github.com/jOOQ/jOOQ/issues/11718。我还创建了一个问题,想知道JetBrains是否能对此做些什么:https://youtrack.jetbrains.com/issue/IDEA-265263

而他们已经可以了!除了org.jetbrains.annotations.Contract 注解,显然正是因为这个原因才有的,也可以在每一个 "其返回值需要检查 "的方法上模仿JSR-305@CheckReturnValue 注解(即一个没有副作用的方法,或者其副作用是只变异"this")。

我添加了这个注解,我把它添加到所有相关的jOOQ API中,这是一个有点像牦牛剃头的过程(https://github.com/jOOQ/jOOQ/commit/f2b529a2305f8c5f8d037776687887a5acd50b11),然后就看到了

imageimage

正如你所看到的,现在IntelliJ在用户忘记消耗jOOQ的任何DSL方法的结果时都会发出警告(通过调用execute() ,将其传递给一些消耗它的方法,等等)。