generate enum class from table with JOOQ
I think you should be able to use an EnumConverter
public class YNMConverter extends EnumConverter<String, YNM > {
public YNMConverter() {
super(String.class, YNM.class);
}
}
You will then need to add it to the codegen as a custom type and a forced type. Here is a programatic example
new CustomType()
.withName("YNM")
.withType(YNM.class.getName())
.withConverter(YNMConverter.class.getName());
new ForcedType()
.withTypes("varchar")
.withName("YNM")
.withExpression(".*ynm.*") // regex to match the column name
You need to add the forced type and custom type to the codegen. This is can be done in maven / xml or programatically
Sure, you could re-implement the removed feature on your side in a few steps:
1. Implement the generator for that enum
You would need to override the JavaGenerator
to implement the code generation for the translation of your master data (might be several tables) to enums. How that works is entirely up to you, e.g. you could have:
- Single column master data tables
- ID/VALUE mapping tables
- ID/VALUE/Comment mapping tables
- Other layouts
2. Generate ForcedType
configurations for those enums
Whenever such a master data table is referenced, you should re-wire the foreign key column to that enum using a <forcedType/>
configuration. This is best done by configuring your code generation programmatically, as that would allow you to have more dynamic control over your jOOQ code generation configuration.
This step is documented more in detail in Bill O'Neil's answer.
3. Prevent the generation of the master data tables
In addition to the above, you should probably remove the master data tables themselves from your generated output. In your case, this should result in the configuration:
<excludes>YNM</excludes>
Or, if you have more than one master data table:
<excludes>YNM|OTHER_MASTER_DATA_TABLE|...</excludes>
Excluding these tables will prevent accessing them from jOOQ client code, as well as remove foreign key information in generated code, which might be confusing.
I know this is an old question, but I'm posting my answer since it might be useful for others.
I had to face the same needs and it was very difficult to achieve, so here you can find the code I implemented to generate enums from an enums
schema.
The code was implemented in groovy, but for java it's very similar.
First and very important, I had to create a separate project for my enum generator since it will work as a dependency for the project that is going to use it. This is needed because the project generating the code must run the enum generator at compilation time, so the way to achieve this is by adding the enum generator as a dependency.
Enum generator project dependency
package com.ctg.jooqgenerator.jooq
import org.jooq.codegen.JavaGenerator
import org.jooq.codegen.JavaWriter
import org.jooq.meta.Database
import org.jooq.meta.SchemaDefinition
import org.jooq.meta.TableDefinition
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.sql.ResultSet
class EnumGenerator extends JavaGenerator {
private static final String ENUMS_SCHEMA = "enums"
private static final Logger log = LoggerFactory.getLogger(EnumGenerator.class)
@Override
void generateSchema(SchemaDefinition schema) {
// Apply custom logic only for `enums` schema. Others schema has regular generation
if (schema.name != ENUMS_SCHEMA) {
super.generateSchema(schema)
return
}
log.info("Generating enums")
log.info("----------------------------------------------------------")
Database db = schema.database
db.getTables(schema).each { TableDefinition table ->
// Prepare enum name from snake_case to CamelCase
String enumName = table.name.replaceAll('_([a-z])') { it[1].capitalize() }.capitalize()
JavaWriter out = newJavaWriter(new File(getFile(schema).getParentFile(), "${enumName}.java"))
log.info("Generating enum: {}.java [input={}, output={}]", enumName, table.name, enumName)
printPackage(out, schema)
out.println("public enum $enumName {")
ResultSet rs = db.connection.prepareStatement("SELECT * FROM ${schema}.\"${table.name}\"").executeQuery()
while (rs.next()) {
String name = rs.getString('name'),
description = rs.getString('description'),
s = rs.isLast() ? ";" : ","
// Generate enum entry
out.tab(1).println("$name(\"$description\")$s")
}
out.println("""
| private final String description;
|
| private $enumName(String description) {
| this.description = description;
| }
|}
""".stripMargin())
closeJavaWriter(out)
}
log.info("----------------------------------------------------------")
super.generateSchema(schema)
}
}
Database having enum tables
The tables that will be translated to enums look like this:
-- Table name `account_role` will be translated into `AccountRole`
CREATE TABLE enums.account_role (
"name" varchar(100) NOT NULL,
description varchar(255) NOT NULL,
CONSTRAINT account_role_name_key UNIQUE (name)
);
-- Table entries will be translated into enum entries
INSERT INTO enums.account_role ("name",description) VALUES
('BILLING','Role for contact/address that will be a Billing contact/address'),
('PAYMENT','Role for contact/address that will be a Payment contact/address'),
('SERVICE','Role for contact/address that will be a Service contact/address'),
('SOLD_TO','Role for contact/address that will be a SoldTo contact/address')
;
This data definition will result in below autogenerated enum AccountRole.java:
/*
* This file is generated by jOOQ.
*/
package com.congerotechnology.ctgcommon.jooq.enums;
public enum AccountRole {
BILLING("Role for contact/address that will be a Billing contact/address"),
PAYMENT("Role for contact/address that will be a Payment contact/address"),
SERVICE("Role for contact/address that will be a Service contact/address"),
SOLD_TO("Role for contact/address that will be a SoldTo contact/address");
private final String description;
private AccountRole(String description) {
this.description = description;
}
}
Main project
Then on the main project that is going to use this enum generator I have set the following maven code on pom.xml
:
<dependencies>
...
<!-- JOOQ custom generator -->
<dependency>
<groupId>com.ctg</groupId>
<artifactId>ctg-jooq-generator</artifactId>
<version>0.0.1</version>
</dependency>
...
</dependencies>
<build>
...
<plugins>
<!-- JOOQ code generation -->
<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<version>${jooq.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<jdbc>
<driver>org.postgresql.Driver</driver>
<url>jdbc:postgresql://${env.DB_URL}</url>
<user>${env.DB_USER}</user>
<password>${env.DB_PASSWORD}</password>
</jdbc>
<generator>
<name>com.ctg.ctgjooqgenerator.jooq.EnumGenerator</name>
<database>
<name>org.jooq.meta.postgres.PostgresDatabase</name>
<includes>.*</includes>
<excludes />
<dateAsTimestamp>true</dateAsTimestamp>
<inputSchema>enums</inputSchema>
</database>
<generate>
<deprecated>false</deprecated>
<instanceFields>true</instanceFields>
</generate>
<target>
<packageName>com.ctg.ctgcommon.jooq.enums</packageName>
<directory>target/generated-sources/jooq-postgres</directory>
</target>
</generator>
</configuration>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgresql.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>