简体   繁体   中英

Why does overriding the jOOQ strategy break copying from POJOs to Records?

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.

The database schema

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.

The generator

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( "_", "" );
    }
}

The problem

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:

  1. Method names for field setters use the standard name ( setFoo for a DB column named foo or FOO ), or
  2. Field names use the standard name ( foo 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); 
 }

Workaround

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM