I'm writing a custom code generator where each master data table has its own java enum.
I use the forcedType settings in the JOOQ configuration to map every use of the table to the enum, which works fine.
I'm working on removing the unnecessary generated classes like the POJO, DAO, and Record and came up with 2 options.
- Exclude table from code generation
Using the <excludes>table_name_which_is_an_enum_in_java</excludes> flag however this also messes up the code generation for my enum, because the tables in the schema do not contain the excluded table anymore meaning I cannot convert it to an enum.
- Manually skip code generation in custom generator
The idea is to check every relevant generation method and skip the table if it's the table which should be converted to an enum. This works fine for
- POJOs with
generatePOJO - DAOs with
generateDAO - Records with
generateRecords
To prevent the table generation I remove the table from the database object (to my surprise the returned list is mutable).
protected void generateSchema(SchemaDefinition schema) {
//enum generation logic
List<TableDefinition> tableDefinitions = db.getTables(schema);
TableDefinition toRemove = db.getTable(schema, "table_name_which_is_an_enum_in_java", true);
boolean removed = tableDefinitions.remove(toRemove);
if(removed) {
log.info("Removed table {} from code generation", toRemove);
}
}
But I have trouble removing the foreign key relations.
When I override printForeignKey and only call the parent method if the foreign key's referenced table is not the table which should be converted to an enum, then the generated Keys class does not generate the foreign key, however it still attemps to import the record, which does not exist.
@Override
protected void printForeignKey(JavaWriter out, int foreignKeyCounter, ForeignKeyDefinition foreignKey, boolean distributeForeignKey) {
if(foreignKey.getReferencedTable().getName().equalsIgnoreCase("table_name_which_is_an_enum_in_java")) {
return;
}
super.printForeignKey(out, foreignKeyCounter, foreignKey, distributeForeignKey);
}
Another problem is the table where the foreign key is located in. A reference method and a transient field with another method are being created. This is just an example:
//class StammdatenZustand and Keys.FK_SPIELZEUG_STAMMDATEN_ZUSTAND do not exist anymore
@Override
@Nonnull
public List<ForeignKey<SpielzeugRecord, ?>> getReferences() {
return Arrays.asList(Keys.FK_SPIELZEUG_STAMMDATEN_ZUSTAND);
}
private transient StammdatenZustand _stammdatenZustand;
public StammdatenZustand stammdatenZustand() {
if (_stammdatenZustand == null)
_stammdatenZustand = new StammdatenZustand(this, Keys.FK_SPIELZEUG_STAMMDATEN_ZUSTAND);
return _stammdatenZustand;
}
I dug into the source code of JavaGenerator and found the code causing the trouble, but I don't know how to find a workaround.
The easiest solution would be to be able to modify the list that is being returned with tableDefinition.getForeignKeys(tableWhichWillBeAnEnum) and then call clear() on that, but sadly this time the list is not mutable.
EDIT: My current results are the following:
This is the table I want to convert into an enum (table name is "stammdaten_zustand")
with the following data
and this is the table where the pk is referenced (table name is "spielzeug")
My custom generator generates the following enum for the first table
public enum StammdatenZustandEnum {
GUT("Das Produkt ist fast neuwertig.", 1, false),
MITTEL("Einige Gebrauchsspuren sind vorhanden, die vermutlich einen Einfluss auf den Preis haben.", 2, true),
SCHLECHT("Das Produkt ist in einem schlechten Zustand. Verkaufen wird sich kaum lohnen.", 3, true),
UNBEKANNT("Zustand des Produkts ist nicht bekannt.", 4, true);
private final String beschreibung;
private final Integer testInt;
private final boolean testBool;
private StammdatenZustandEnum(String beschreibung,Integer testInt,boolean testBool) {
this.beschreibung = beschreibung;
this.testInt = testInt;
this.testBool = testBool;
}
public String getBeschreibung() {
return this.beschreibung;
}
public Integer getTestInt() {
return this.testInt;
}
public boolean isTestBool() {
return this.testBool;
}
}
In the pom.xml of the project I also use a converter to map everything to the generated enum.
<forcedType>
<userType>model.db.jooq.StammdatenZustandEnum</userType>
<enumConverter>true</enumConverter>
<includeExpression>.*\.Zustand_Kuerzel</includeExpression>
<includeTypes>.*</includeTypes>
</forcedType>
And for example the generated POJO "Spielzeug" is mapped correctly.
public class Spielzeug implements Serializable {
private static final long serialVersionUID = 1L;
private Integer produktId;
private String produktname;
private Double kaufpreis;
private Boolean verkaeuflich;
private StammdatenZustandEnum zustandKuerzel; // mapped to enum
...
Which means I already do what you suggest if I understood you correctly?
However the generated table for "Spielzeug" still generates the following snippet
@Override
@Nonnull
public List<ForeignKey<SpielzeugRecord, ?>> getReferences() {
return Arrays.asList(Keys.FK_SPIELZEUG_STAMMDATEN_ZUSTAND);
}
private transient StammdatenZustand _stammdatenZustand;
public StammdatenZustand stammdatenZustand() {
if (_stammdatenZustand == null)
_stammdatenZustand = new StammdatenZustand(this, Keys.FK_SPIELZEUG_STAMMDATEN_ZUSTAND);
return _stammdatenZustand;
}
and the Keys class attempts to generate a foreign key
public static final ForeignKey<SpielzeugRecord, StammdatenZustandRecord> FK_SPIELZEUG_STAMMDATEN_ZUSTAND = Internal.createForeignKey(Spielzeug.SPIELZEUG, DSL.name("FK_spielzeug_stammdaten_zustand"), new TableField[] { Spielzeug.SPIELZEUG.ZUSTAND_KUERZEL }, Keys.KEY_STAMMDATEN_ZUSTAND_PRIMARY, new TableField[] { StammdatenZustand.STAMMDATEN_ZUSTAND.KUERZEL }, true);
But both snippets throw errors because the "StammdatenZustand" POJO and Record do not exist.
On a side note: Generally speaking the mapping works and there are no erros when I just leave the generated Dao, POJO and Record. In this case I just have to tell the end user to basically ignore these classes and favour the generated enum.


