We use the https://github.com/etiennestuder/gradle-jooq-plugin for generating jOOQ classes on-demand from our database (DDL, .sql
file with CREATE TABLE
statements). However, we noted that when overriding the strategy.name
in jooq.configurations.main.generationTool.generator
, we started seeing peculiar behavior.
We have some field names like _is_tombstone
, _revision
etc in our tables. These are for "metadata" which differs from the normal "data" columns (data coming from another system vs "metadata" logging event details about why the change was triggered).
Other tables like id
, name
etc do not have any special prefix.
Here is our current generator strategy, inspired by https://www.jooq.org/doc/latest/manual/code-generation/codegen-generatorstrategy/
public class CustomNameGeneratorStrategy extends DefaultGeneratorStrategy {
@Override
public String getJavaMemberName( Definition definition, Mode mode ) {
String memberName = super.getJavaMemberName( definition, mode );
// Converts e.g. _IsTombstone to _isTombstone
if ( memberName.startsWith( "_" ) ) {
memberName = "" + memberName.charAt( 0 ) + toLowerCase( memberName.charAt( 1 ) ) + memberName.substring( 2 );
}
return memberName;
}
@Override
public String getJavaGetterName( Definition definition, Mode mode ) {
String methodName = super.getJavaGetterName( definition, mode );
methodName = methodName.replace( "_", "" );
// isTombstone() seems more natural than getIsTombstone()
methodName = methodName.replace( "getIs", "is" );
return methodName;
}
@Override
public String getJavaSetterName( Definition definition, Mode mode ) {
String methodName = super.getJavaSetterName( definition, mode );
return methodName.replace( "_", "" );
}
}
With the above in place, the code below causes some very nasty bugs with certain fields not copied from the POJO to the Record
instance. Only id
, name
etc works. All fields which have underscores in the name get excluded in the copying; they have null
values in the target Record
instance.
This, in turns, makes the DB insertion fail since certain mandatory fields do not have any values.
import static some.package.Tables.GROUPS;
import some.package.tables.records.GroupRecord;
import some.package.tables.pojos.TSDBGroup;
// ...
TSDBGroup tsdbGroup = createTsdbGroup(...);
// The GroupRecord here becomes a "partial copy".
GroupRecord groupRecord = create.newRecord(GROUPS, tsdbGroup);
groupRecord.store();
Why does this happen?
The problem turned out to be that jOOQ expects one of the following to hold true, unless you annotate your getters/setters with JPA-style annotations:
setFoo
for a DB column named foo
or FOO
), orfoo
for a DB column named foo
or FOO
)Break both of these rules, and you keep to keep the pieces. :-)
More specifically, this is caused by the following code in jOOQ :
// No annotations are present
else {
members = getMatchingMembers(configuration, type, field.getName(), true);
method = getMatchingGetter(configuration, type, field.getName(), true);
}
// Use only the first applicable method or member
if (method != null)
Tools.setValue(record, field, method.invoke(source));
else if (members.size() > 0)
setValue(record, source, members.get(0), field);
}
The simple workaround is to remove the getJavaMemberName
method in the custom GeneratorStrategy
. jOOQ is then able to populate the fields as expected when creating Record
s from POJOs.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.