javajooqjooq-codegen

How to map table and column names to human readable using jooq generator?


I have some legacy database with table and column names like:

XYZEMP:

that could be mapped to human readable

EMPLOYEE

When I use standard JOOQ code generation it creates Table object XYXEMP, XyzempRecord etc. with XYZCMP columns and respective getters and setters. Is there any way to pass mapping to the generator so it produces Table object Employee, EmployeeRecord and human readable column names as well?

My idea is to use Custom generator strategy

public class AsInDatabaseStrategy extends DefaultGeneratorStrategy {
    @Override
    public String getJavaClassName(Definition definition, Mode mode) {
        Map<String, String> tableNamesMapping = readTableNames();
        if (mode == Mode.DEFAULT){ //for table class
             String readableName = tableNamesMapping.get(definition.getOutputName());
             if (readableName == null){
               throw new IllegalStateException("Table " + definition.getOutputName() + " lacks mapping");
             }
             return readableName;
        } else if (mode == Mode.RECORD) { // for record
            // similar logic for record
            return readableName + "Record";
        }
        return super.getJavaClassName(definition, mode);
    }
    @Override
    public String getJavaIdentifier(Definition definition) {
    // somehow similar code for table and and column
    }
    @Override
    public String getJavaSetterName(Definition definition, Mode mode) {
        // somehow similar code for table and and column
    }
    @Override
    public String getJavaGetterName(Definition definition, Mode mode) {
        // somehow similar code for table and and column
    }
    private Map<String, String> readTableNames(){
    //read names mapping from file
    }
    private Map<String, Map<String, String>> readColumnNames(){
    //read names mapping from file
    }
}

Mapping files could be for tables:

{
"XYZEMP" : "EMPLOYEE",
...
}

for columns

{
"XYZEMP" : {
"XYZCMP" : "COMPANY",
"XYZUSR: : "USERNAME",
"XYZNME" : "NAME"
}
...
}

Do you see smarter way for doing that? In case of my approach - how to distinguish with "Definition" object is it table or column (or any other object) and for columns which table it belongs to?


Solution

  • Answering your question

    Do you see smarter way for doing that?

    That looks reasonable to me. The alternative is to use the configurative "matcher strategy", where you can configure those mappings directly in the Maven/Gradle/standalone XML format. That approach would seem more verbose and repetitive than yours, I think.

    how to distinguish with "Definition" object is it table or column (or any other object) and for columns which table it belongs to?

    Just check if definition instanceof TableDefinition or definition instanceof ColumnDefinition, and use their APIs to find table/column relationships.

    Side effects

    Please note that if you rename your column names in Java using a GeneratorStrategy, jOOQ 3.19 won't map the database names to your renamed POJO properties automatically. E.g. when you do:

    ctx.select(EMPLOYEE.NAME)
       .from(EMPLOYEE)
       .fetchInto(Employee.class);
    

    The DefaultRecordMapper won't be aware of this renaming. It will still see the XYZNME column name, which the Employee POJO doesn't have any correspondence to, unless you tell jOOQ to generate annotations:

    public class Employee {
        @Column("XYZNME")
        String name;
    }
    

    This only affects the DefaultRecordMapper