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>