spring-boot-data-r2dbc-jooq
spring-boot-data-r2dbc-jooq copied to clipboard
Add support for queries using `*ResultStep#returningResult`
In JOOQ there are 2 general ways to declare the returning clause (for update/insert/delete). Those are [Insert|Update|Delete]ResultStep#returning
and [Insert|Update|Delete]ResultStep#returningResult
where the latter is to allow returning different record type than the one representing the table (e.g. Record1<UUID>
instead of UserRecord
with just one field actually present (if that's all you need)).
Currently only the first approach is supported. It would be useful to support the latter as well because it currently fails with ClassCastException
at runtime. Example output: java.lang.ClassCastException: class com...model.tables.records.UserRecord cannot be cast to class org.jooq.Record1
it currently fails with ClassCastException at runtime. Example output: java.lang.ClassCastException: class com...model.tables.records.UserRecord cannot be cast to class org.jooq.Record1
What is the behaviour of JOOQ in this case? Can you please provide a code sample that results in this error?
The problems is that the method ReactiveJooq#executeReturning
(called by ReactiveJooq#executeReturningOne
below) always creates records of table's type. In other words, the assumption that the insert/update query's generic type matches the record type of the table is incorrect when using returningResult
. I've provided 2 tests showing the differences (the second one fails). I've extracted the queries into variables to emphasize on the types. Apart from the last line in the query and the map
usage the tests are identical.
@Test
void testWithReturning() {
InsertResultStep<ProcessedEventsRecord> insert = dslContext
.insertInto(PROCESSED_EVENTS)
.set(PROCESSED_EVENTS.ID, randomUUID())
.set(PROCESSED_EVENTS.CONTENT, "content")
.returning(PROCESSED_EVENTS.ID);
executeReturningOne(insert)
.map(ProcessedEventsRecord::getId)
.block(); // works
}
@Test
void testWithReturningResult() {
InsertResultStep<Record1<UUID>> insert = dslContext
.insertInto(PROCESSED_EVENTS)
.set(PROCESSED_EVENTS.ID, randomUUID())
.set(PROCESSED_EVENTS.CONTENT, "content")
.returningResult(PROCESSED_EVENTS.ID);
executeReturningOne(insert)
.map(Record1::value1)
.block(); // ClassCastException
}
Where the table in use is generated from:
CREATE TABLE processed_events
(
id UUID PRIMARY KEY,
content VARCHAR NOT NULL
);