All versions: 3.11 | 3.10 | 3.9 | Development versions: 3.12

The code generator allows users to override column data types in three different ways:

All of this can be done using forced types.

Data type rewriting

XML configuration (standalone and Maven)

<configuration xmlns="http://www.jooq.org/xsd/jooq-codegen-3.11.0.xsd">
  <generator>
    <database>
      <!-- The first matching forcedType will be applied to the data type definition. -->
      <forcedTypes>
        <forcedType>

          <!-- Specify any data type that is supported in your database, or if unsupported, a type from org.jooq.impl.SQLDataType -->
          <name>BOOLEAN</name>

          <!-- Add a Java regular expression matching fully-qualified columns. Use the pipe to separate several expressions.
               If provided, both "expressions" and "types" must match. -->
          <expression>.*\.IS_VALID</expression>
          
          <!-- Add a Java regular expression matching data types to be forced to have this type.

               Data types may be reported by your database as:
               - NUMBER              regexp suggestion: NUMBER
               - NUMBER(5)           regexp suggestion: NUMBER\(5\)
               - NUMBER(5, 2)        regexp suggestion: NUMBER\(5,\s*2\)
               - any other form.

               It is thus recommended to use defensive regexes for types.

               If provided, both "expressions" and "types" must match. -->
          <types>.*</types>
          
          <!-- Force a type on ALL / NULL (nullable) / NOT_NULL (non-nullable) types -->
          <nullability>ALL</nullability>
        </forcedType>
      </forcedTypes>
    </database>
  </generator>
</configuration>

Programmatic configuration

configuration
  .withGenerator(new Generator(
    .withDatabase(new Database()
      // The first matching forcedType will be applied to the data type definition.
      .withForcedTypes(new ForcedType()
        .withName("BOOLEAN")
        .withExpression(".*\.IS_VALID")
        .withTypes(".*")
        .withNullability(Nullability.ALL)))));

Gradle configuration

myConfigurationName(sourceSets.main) {
  generator {
    database {
      // The first matching forcedType will be applied to the data type definition.
      forcedTypes {
        forcedType {
          name = 'BOOLEAN'
          expression = '.*\.IS_VALID'
          types = '.*'
          nullability = ALL
        }
      }
    }
  }
}

Mapping to user type with a converter

Both user type mappings work the same way, regardless if you're using a org.jooq.Converter or a org.jooq.Binding.

XML configuration (standalone and Maven)

<configuration xmlns="http://www.jooq.org/xsd/jooq-codegen-3.11.0.xsd">
  <generator>
    <database>
      <!-- The first matching forcedType will be applied to the data type definition. -->
      <forcedTypes>
        <forcedType>

          <!-- Specify the Java type of your custom type. This corresponds to the Converter's <U> type. -->
          <userType>java.time.Instant</userType>

          <!-- Associate that custom type with your converter. -->
          <converter>com.example.LongToInstantConverter</converter>

          <!-- These are the same as for type rewriting -->
          <expression>.*\.DATE_OF_.*</expression>
          <types>.*</types>
        </forcedType>
      </forcedTypes>
    </database>
  </generator>
</configuration>

Programmatic configuration

configuration
  .withGenerator(new Generator(
    .withDatabase(new Database()
      // The first matching forcedType will be applied to the data type definition.
      .withForcedTypes(new ForcedType()
        .withUserType("java.time.Instant")
        .withConverter("com.example.LongToInstantConverter")
        .withExpression(".*\.DATE_OF_.*")
        .withTypes(".*")))));

Gradle configuration

myConfigurationName(sourceSets.main) {
  generator {
    database {
      // The first matching forcedType will be applied to the data type definition.
      forcedTypes {
        forcedType {
          userType = 'java.time.Instant'
          converter = 'com.example.LongToInstantConverter'
          expression = '.*\.DATE_OF_.*'
          types = '.*'
        }
      }
    }
  }
}

For more information about using converters, please refer to the manual's section about custom data type conversion.

Mapping to user type with an inline converter

For convenience, you can inline your converter code directly into the configuration instead of providing a class reference.

XML configuration (standalone and Maven)

<configuration xmlns="http://www.jooq.org/xsd/jooq-codegen-3.11.0.xsd">
  <generator>
    <database>
      <!-- The first matching forcedType will be applied to the data type definition. -->
      <forcedTypes>
        <forcedType>

          <!-- Specify the Java type of your custom type. This corresponds to the Converter's <U> type. -->
          <userType>com.example.MyEnum</userType>

          <!-- Associate that custom type with your inline converter. -->
          <converter>org.jooq.Converter.ofNullable(Integer.class, MyEnum.class, i -> MyEnum.values()[i], MyEnum::ordinal)</converter>

          <!-- These are the same as for type rewriting -->
          <expression>.*\.DATE_OF_.*</expression>
          <types>.*</types>
        </forcedType>
      </forcedTypes>
    </database>
  </generator>
</configuration>

Programmatic configuration

configuration
  .withGenerator(new Generator(
    .withDatabase(new Database()
      // The first matching forcedType will be applied to the data type definition.
      .withForcedTypes(new ForcedType()
        .withUserType("com.example.MyEnum")
        .withConverter("org.jooq.Converter.ofNullable(Integer.class, MyEnum.class, i -> MyEnum.values()[i], MyEnum::ordinal)")
        .withExpression(".*\.DATE_OF_.*")
        .withTypes(".*")))));

Gradle configuration

myConfigurationName(sourceSets.main) {
  generator {
    database {
      // The first matching forcedType will be applied to the data type definition.
      forcedTypes {
        forcedType {
          userType = 'com.example.MyEnum'
          converter = 'org.jooq.Converter.ofNullable(Integer.class, MyEnum.class, i -> MyEnum.values()[i], MyEnum::ordinal)'
          expression = '.*\.DATE_OF_.*'
          types = '.*'
        }
      }
    }
  }
}

Mapping to an enum user type with a converter

If your user type is a Java enum, you can use the <enumConverter/> convenience flag instead of an explicit converter per enum type. This will apply the built-in org.jooq.impl.EnumConverter.

XML configuration (standalone and Maven)

<configuration xmlns="http://www.jooq.org/xsd/jooq-codegen-3.11.0.xsd">
  <generator>
    <database>
      <!-- The first matching forcedType will be applied to the data type definition. -->
      <forcedTypes>
        <forcedType>

          <!-- Specify the Java type of your custom type. This corresponds to the Converter's <U> type. -->
          <userType>com.example.MyEnum</userType>

          <!-- Apply the built in org.jooq.impl.EnumConverter. -->
          <enumConverter>true</enumConverter>

          <!-- These are the same as for type rewriting -->
          <expression>.*\.MY_STATUS</expression>
          <types>.*</types>
        </forcedType>
      </forcedTypes>
    </database>
  </generator>
</configuration>

Programmatic configuration

configuration
  .withGenerator(new Generator(
    .withDatabase(new Database()
      // The first matching forcedType will be applied to the data type definition.
      .withForcedTypes(new ForcedType()
        .withUserType("com.example.MyEnum")
        .withEnumConverter(true)
        .withExpression(".*\.MY_STATUS")
        .withTypes(".*")))));

Gradle configuration

myConfigurationName(sourceSets.main) {
  generator {
    database {
      // The first matching forcedType will be applied to the data type definition.
      forcedTypes {
        forcedType {
          userType = 'com.example.MyEnum'
          enumConverter = true
          expression = '.*\.MY_STATUS'
          types = '.*'
        }
      }
    }
  }
}

Mapping to user type with a binding

Just switch the converter configuration to a binding configuration.

XML configuration (standalone and Maven)

<configuration xmlns="http://www.jooq.org/xsd/jooq-codegen-3.11.0.xsd">
  <generator>
    <database>
      <!-- The first matching forcedType will be applied to the data type definition. -->
      <forcedTypes>
        <forcedType>

          <!-- Specify the Java type of your custom type. This corresponds to the Binding's <U> type. -->
          <userType>java.time.Instant</userType>

          <!-- Associate that custom type with your converter. -->
          <binding>com.example.LongToInstantBinding</binding>

          <!-- These are the same as for type rewriting -->
          <expression>.*\.DATE_OF_.*</expression>
          <types>.*</types>
        </forcedType>
      </forcedTypes>
    </database>
  </generator>
</configuration>

Programmatic configuration

configuration
  .withGenerator(new Generator(
    .withDatabase(new Database()
      // The first matching forcedType will be applied to the data type definition.
      .withForcedTypes(new ForcedType()
        .withUserType("java.time.Instant")
        .withBinding("com.example.LongToInstantBinding")
        .withExpression(".*\.DATE_OF_.*")
        .withTypes(".*")))));

Gradle configuration

myConfigurationName(sourceSets.main) {
  generator {
    database {
      // The first matching forcedType will be applied to the data type definition.
      forcedTypes {
        forcedType {
          userType = 'java.time.Instant'
          binding = 'com.example.LongToInstantBinding'
          expression = '.*\.DATE_OF_.*'
          types = '.*'
        }
      }
    }
  }
}

For more information about using converters, please refer to the manual's section about custom data type bindings.

The jOOQ Logo