Open sargue opened 9 months ago
Thanks for your report. I can reproduce the issue. Will look into this right away.
I see, this is because the jOOQ DefaultRecordMapper
treats both from(...)
and setFrom(...)
methods as setters for the FROM
attribute, see the specification here:
https://www.jooq.org/javadoc/latest/org.jooq/org/jooq/impl/DefaultRecordMapper.html
This would also happen with other attribute names conflicting with methods, including into
or wait
(from java.lang.Object
):
org.jooq.exception.MappingException: An error occurred when mapping record to class org.jooq.test.mariadb.generatedclasses.tables.pojos.Event
at org.jooq.impl.DefaultRecordMapper$MutablePOJOMapper.map(DefaultRecordMapper.java:925)
at org.jooq.impl.DefaultRecordMapper.map(DefaultRecordMapper.java:649)
at org.jooq.RecordMapper.apply(RecordMapper.java:87)
at org.jooq.impl.DefaultRecordMapper.apply(DefaultRecordMapper.java:1)
at java.base/java.util.stream.Collectors.lambda$mapping$13(Collectors.java:432)
at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1939)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at org.jooq.impl.AbstractCursor.collect(AbstractCursor.java:78)
at org.jooq.impl.ResultQueryTrait.collect(ResultQueryTrait.java:361)
at org.jooq.impl.ResultQueryTrait.fetch(ResultQueryTrait.java:1465)
at org.jooq.impl.DAOImpl.findAll(DAOImpl.java:321)
at org.jooq.testscripts.JDBC.main(JDBC.java:35)
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:118)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.jooq.impl.DefaultRecordMapper$MutablePOJOMapper.map(DefaultRecordMapper.java:893)
... 17 more
Caused by: java.lang.IllegalMonitorStateException: current thread is not owner
at java.base/java.lang.Object.wait0(Native Method)
at java.base/java.lang.Object.wait(Object.java:366)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
... 19 more
It's not really related to code generation or even using DAOs. Generating interfaces is why the conflicting from()
method is causing trouble, but again, conflicts can also arise with methods from java.lang.Object
.
It should be simple to fix the conflicts caused by java.lang.Object
: If both wait
and setWait
methods are found, and wait
is from java.lang.Object
, then don't call it.
Your case is a bit more tricky because it might not be obvious what is intended as a setter and what isn't. The from()
and into()
methods aren't recognisable as such by the jOOQ runtime. They're simply code generation artifacts, and could also be written manually by a "custom code section."
I guess the main hint we can take here is that the argument type doesn't match the type of the getter (getFrom()
returns String
), but that shouldn't matter according to DefaultRecordMapper
.
I don't think there's a very simple fix here. The reflection based DefaultRecordMapper
will always run into such conflict risks... Will think about it a bit more.
Well, there is always an option to slightly tweak the DAO.mapper()
to handle such cases, because it works on generated code. It would be a more local fix to your specific setup, not a generic fix, so preferable only if there's no reasonable generic fix.
Interesting. In my case it has a very easy solution, I'm still designing the database structure so I will go with another name. It's not a big deal. And I will try to remember to avoid reserved words in the future (which sounds like a reasonable advice not just for jOOQ, now that I think about it).
Hey, is not that different from other preventive precautions like avoiding non-ASCII or spaces for file names, or things like that, which experience reminds you of now and then.
But I understand that, for your point of view as an API developer, this is a bit of a PITA.
(which sounds like a reasonable advice not just for jOOQ, now that I think about it).
Well, jOOQ tries hard to make all these edge cases work somehow, but being edge cases, they keep popping up here and there. Just today, I've updated this integration test table to make sure all 3 supported languages can compile jOOQ-generated code :)
CREATE TABLE reserved(
id INT,
"abstract" INT,
"case" INT,
"catch" INT,
"class" INT,
"def" INT,
"do" INT,
"else" INT,
"extends" INT,
"false" INT,
"final" INT,
"finally" INT,
"for" INT,
"forSome" INT,
"if" INT,
"implicit" INT,
"import" INT,
"lazy" INT,
"match" INT,
"new" INT,
"null" INT,
"object" INT,
"override" INT,
"package" INT,
"private" INT,
"protected" INT,
"return" INT,
"sealed" INT,
"super" INT,
"this" INT,
"throw" INT,
"trait" INT,
"try" INT,
"true" INT,
"type" INT,
"val" INT,
"var" INT,
"while" INT,
"with" INT,
"yield" INT,
CONSTRAINT pk_reserved PRIMARY KEY (id)
);
But I understand that, for your point of view as an API developer, this is a bit of a PITA.
Well, it never gets dull! :)
Expected behavior
Any valid column name should work with code generation and DAO. I've found that a column named "from" raises an exception. I've initially detected it with version 3.15.12 but reproduced it also with version 3.19.3.
Actual behavior
It fails with a message about a converter:
Steps to reproduce the problem
I'm managed to reproduce the problem with a small set-up.
I've started an empty MariaDB instance using Docker.
docker run -p 3306:3306 --env MARIADB_ROOT_PASSWORD=my-secret-pw mariadb:latest
Then I connected to MariaDB to create a schema called
testdb
as well as a simple table:Please note the "from" column name, as it needs to be quoted due to "from" being a reserved keyword. Also note the insert, as you need at least a row to reproduce the problem.
Then I create a simple gradle-based project:
With a single Main class:
Then it's all about generating the jOOQ classes, including DAOs as per the configuration, and running the main class. The result is the exception posted above.
Just renaming the column to something different (e.g. "fromm") works fine.
jOOQ Version
jOOQ OSS 3.19.3
Database product and version
MARIADB: 11.2.3-MariaDB-1:11.2.3+maria~ubu2204
Java Version
Liberica JDK 17.0.10
OS Version
Windows 10 Pro 19045.4046
JDBC driver name and version (include name if unofficial driver)
org.mariadb.jdbc:mariadb-java-client:3.3.2