jOOQ’s DSL, like all fluent API, has one huge caveat. It’s very straightforward to overlook to name .execute()
. And if you do, chances are high, you’re going to be watching your code for minutes, as a result of all the pieces seems excellent:
ctx.insertInto(T)
.columns(T.A, T.B)
.values(1, 2);
Staring… staring… staring… Why is it not inserting that row?
“Aaaah, not once more!!”
That is the way it’s performed:
ctx.insertInto(T)
.columns(T.A, T.B)
.values(1, 2)
.execute();
In precept, this type of mistake can occur with any fluent API. E.g. StringBuilder
sb.append("a").append("b"); // Not consuming the outcome
Or streams:
Stream.of(1, 2).peek(System.out::println); // Not a lot peeking
Nevertheless it often doesn’t occur as a lot, as a result of the distinction to jOOQ is that
- jOOQ’s DML statements (
INSERT
,UPDATE
,DELETE
,MERGE
) and DDL statements (CREATE
,ALTER
,DROP
,TRUNCATE
), and some different produce a facet impact - That facet impact is the one factor we care about. The outcome (the replace depend) is generally irrelevant
And as such, we don’t care about the results of execute()
, which is an int
. Nobody forgets to name fetch()
on a jOOQ ResultQuery
:
ctx.choose(T.A, T.B)
.from(T); // Nicely duh
As a result of with out calling fetch()
or one thing related, we’re not getting any outcomes, and we wish the outcomes, identical to with the StringBuilder
or the Stream
. However we don’t need the execute()
outcome.
As such, even we, when writing jOOQ’s integration checks, sometimes overlook to name this foolish little technique.
No extra!
When it occurred once more this week…
… I lastly created a problem to consider it: https://github.com/jOOQ/jOOQ/points/11718. And I created a problem to surprise if JetBrains may do one thing about it: https://youtrack.jetbrains.com/subject/IDEA-265263
And so they already can! Aside from the org.jetbrains.annotations.Contract
annotation, which is there for exactly this cause, apparently, it’s additionally attainable to mimick the JSR-305 @CheckReturnValue
annotation on each technique “whose return worth must be checked” (i.e. a way that has no facet impact, or whose facet impact is to mutate solely “this
“).
I added this annotation, I added it to all of the related jOOQ API, which was a little bit of yak shaving (https://github.com/jOOQ/jOOQ/commit/f2b529a2305f8c5f8d037776687887a5acd50b11) and voilà
As you possibly can see, IntelliJ now warns the consumer at any time when they overlook to eat the results of any of jOOQ’s DSL strategies (by calling execute()
, passing it to some technique that consumes it, and many others.)
Thanks once more to Tagir Valeev from JetBrains for strolling me by this and even enhancing the @Contract
annotation, which jOOQ would possibly use in a future model.