Available in versions: Dev (3.20) | Latest (3.19) | 3.18 | 3.17 | 3.16 | 3.15 | 3.14 | 3.13 | 3.12 | 3.11 | 3.10
This documentation is for the unreleased development version of jOOQ. Click on the above version links to get this documentation for a supported version of jOOQ.
Custom generator strategies
Applies to ✅ Open Source Edition ✅ Express Edition ✅ Professional Edition ✅ Enterprise Edition
Using custom generator strategies to override naming schemes
jOOQ allows you to override default implementations of the code generator or the generator strategy. Specifically, the latter can be very useful if you want to inject custom behaviour into jOOQ's code generator with respect to naming classes, members, methods, and other Java objects.
<configuration> <generator> <!-- A programmatic naming strategy implementation, referened by class name. --> <strategy> <name>com.example.AsInDatabaseStrategy</name> </strategy> </generator> </configuration>
See the configuration XSD, standalone code generation, and maven code generation for more details.
new org.jooq.meta.jaxb.Configuration() .withGenerator(new Generator() // A programmatic naming strategy implementation, referened by class name. .withStrategy(new Strategy() .withName("com.example.AsInDatabaseStrategy") ) )
See the configuration XSD and programmatic code generation for more details.
import org.jooq.meta.jaxb.* configuration { generator { // A programmatic naming strategy implementation, referened by class name. strategy { name = "com.example.AsInDatabaseStrategy" } } }
See the configuration XSD and gradle code generation for more details.
configuration { generator { // A programmatic naming strategy implementation, referened by class name. strategy { name = "com.example.AsInDatabaseStrategy" } } }
See the configuration XSD and gradle code generation for more details.
generationTool { generator { // A programmatic naming strategy implementation, referened by class name. strategy { name = "com.example.AsInDatabaseStrategy" } } }
See the configuration XSD and gradle code generation for more details.
Optionally, instead of referencing a previously compiled GeneratorStrategy
, the strategy code (written in Java) can also be inlined into the configuration, in case of which it will be compiled ad-hoc (see in-memory compilation for more details):
<configuration> <generator> <!-- A programmatic naming strategy implementation, referened by class name. --> <strategy> <name>com.example.AsInDatabaseStrategy</name> <java>package com.example; import org.jooq.codegen.DefaultGeneratorStrategy; public class AsInDatabaseStrategy extends DefaultGeneratorStrategy { ... }</java> </strategy> </generator> </configuration>
See the configuration XSD, standalone code generation, and maven code generation for more details.
new org.jooq.meta.jaxb.Configuration() .withGenerator(new Generator() // A programmatic naming strategy implementation, referened by class name. .withStrategy(new Strategy() .withName("com.example.AsInDatabaseStrategy") .withJava("""package com.example; import org.jooq.codegen.DefaultGeneratorStrategy; public class AsInDatabaseStrategy extends DefaultGeneratorStrategy { ... }""") ) )
See the configuration XSD and programmatic code generation for more details.
import org.jooq.meta.jaxb.* configuration { generator { // A programmatic naming strategy implementation, referened by class name. strategy { name = "com.example.AsInDatabaseStrategy" java = """package com.example; import org.jooq.codegen.DefaultGeneratorStrategy; public class AsInDatabaseStrategy extends DefaultGeneratorStrategy { ... }""" } } }
See the configuration XSD and gradle code generation for more details.
configuration { generator { // A programmatic naming strategy implementation, referened by class name. strategy { name = "com.example.AsInDatabaseStrategy" java = """package com.example; import org.jooq.codegen.DefaultGeneratorStrategy; public class AsInDatabaseStrategy extends DefaultGeneratorStrategy { ... }""" } } }
See the configuration XSD and gradle code generation for more details.
generationTool { generator { // A programmatic naming strategy implementation, referened by class name. strategy { name = "com.example.AsInDatabaseStrategy" java = """package com.example; import org.jooq.codegen.DefaultGeneratorStrategy; public class AsInDatabaseStrategy extends DefaultGeneratorStrategy { ... }""" } } }
See the configuration XSD and gradle code generation for more details.
Make sure your custom generator strategy and its dependencies are available to the code generator as a code generator dependency
The following example shows how you can override the DefaultGeneratorStrategy to render table and column names the way they are defined in the database, rather than switching them to camel case:
/** * It is recommended that you extend the DefaultGeneratorStrategy. Most of the * GeneratorStrategy API is already declared final. You only need to override any * of the following methods, for whatever generation behaviour you'd like to achieve. * * Also, the DefaultGeneratorStrategy takes care of disambiguating quite a few object * names in case of conflict. For example, MySQL indexes do not really have a name, so * a synthetic, non-ambiguous name is generated based on the table. If you override * the default behaviour, you must ensure that this disambiguation still takes place * for generated code to be compilable. * * Beware that most methods also receive a "Mode" object, to tell you whether a * TableDefinition is being rendered as a Table, Record, POJO, etc. Depending on * that information, you can add a suffix only for TableRecords, not for Tables */ public class AsInDatabaseStrategy extends DefaultGeneratorStrategy { /** * Override this to specifiy what identifiers in Java should look like. * This will just take the identifier as defined in the database. */ @Override public String getJavaIdentifier(Definition definition) { // The DefaultGeneratorStrategy disambiguates some synthetic object names, // such as the MySQL PRIMARY key names, which do not really have a name // Uncomment the below code if you want to reuse that logic. // if (definition instanceof IndexDefinition) // return super.getJavaIdentifier(definition); return definition.getOutputName(); } /** * Override these to specify what a setter in Java should look like. Setters * are used in TableRecords, UDTRecords, and POJOs. This example will name * setters "set[NAME_IN_DATABASE]" */ @Override public String getJavaSetterName(Definition definition, Mode mode) { return "set" + definition.getOutputName(); } /** * Just like setters... */ @Override public String getJavaGetterName(Definition definition, Mode mode) { return "get" + definition.getOutputName(); } /** * Override this method to define what a Java method generated from a database * Definition should look like. This is used mostly for convenience methods * when calling stored procedures and functions. This example shows how to * set a prefix to a CamelCase version of your procedure */ @Override public String getJavaMethodName(Definition definition, Mode mode) { return "call" + org.jooq.tools.StringUtils.toCamelCase(definition.getOutputName()); } /** * Override this method to define how your Java classes and Java files should * be named. This example applies no custom setting and uses CamelCase versions * instead */ @Override public String getJavaClassName(Definition definition, Mode mode) { return super.getJavaClassName(definition, mode); } /** * Override this method to re-define the package names of your generated * artefacts. */ @Override public String getJavaPackageName(Definition definition, Mode mode) { return super.getJavaPackageName(definition, mode); } /** * Override this method to define how Java members should be named. This is * used for POJOs and method arguments */ @Override public String getJavaMemberName(Definition definition, Mode mode) { return definition.getOutputName(); } /** * Override this method to define the base class for those artefacts that * allow for custom base classes */ @Override public String getJavaClassExtends(Definition definition, Mode mode) { return Object.class.getName(); } /** * Override this method to define the interfaces to be implemented by those * artefacts that allow for custom interface implementation */ @Override public List<String> getJavaClassImplements(Definition definition, Mode mode) { return Arrays.asList(Serializable.class.getName(), Cloneable.class.getName()); } /** * Override this method to define the suffix to apply to routines when * they are overloaded. * * Use this to resolve compile-time conflicts in generated source code, in * case you make heavy use of procedure overloading */ @Override public String getOverloadSuffix(Definition definition, Mode mode, String overloadIndex) { return "_OverloadIndex_" + overloadIndex; } }
An org.jooq.Table example:
This is an example showing which generator strategy method will be called in what place when generating tables. For improved readability, full qualification is omitted:
package com.example.tables; // 1: ^^^^^^^^^^^^^^^^^^ public class Book extends TableImpl<com.example.tables.records.BookRecord> { // 2: ^^^^ 3: ^^^^^^^^^^ public static final Book BOOK = new Book(); // 2: ^^^^ 4: ^^^^ public final TableField<BookRecord, Integer> ID = /* ... */ // 3: ^^^^^^^^^^ 5: ^^ } // 1: strategy.getJavaPackageName(table) // 2: strategy.getJavaClassName(table) // 3: strategy.getJavaClassName(table, Mode.RECORD) // 4: strategy.getJavaIdentifier(table) // 5: strategy.getJavaIdentifier(column)
An org.jooq.Record example:
This is an example showing which generator strategy method will be called in what place when generating records. For improved readability, full qualification is omitted:
package com.example.tables.records; // 1: ^^^^^^^^^^^^^^^^^^^^^^^^^^ public class BookRecord extends UpdatableRecordImpl<BookRecord> { // 2: ^^^^^^^^^^ 2: ^^^^^^^^^^ public void setId(Integer value) { /* ... */ } // 3: ^^^^^ public Integer getId() { /* ... */ } // 4: ^^^^^ } // 1: strategy.getJavaPackageName(table, Mode.RECORD) // 2: strategy.getJavaClassName(table, Mode.RECORD) // 3: strategy.getJavaSetterName(column, Mode.RECORD) // 4: strategy.getJavaGetterName(column, Mode.RECORD)
A POJO example:
This is an example showing which generator strategy method will be called in what place when generating pojos. For improved readability, full qualification is omitted:
package com.example.tables.pojos; // 1: ^^^^^^^^^^^^^^^^^^^^^^^^ public class Book implements java.io.Serializable { // 2: ^^^^ private Integer id; // 3: ^^ public void setId(Integer value) { /* ... */ } // 4: ^^^^^ public Integer getId() { /* ... */ } // 5: ^^^^^ } // 1: strategy.getJavaPackageName(table, Mode.POJO) // 2: strategy.getJavaClassName(table, Mode.POJO) // 3: strategy.getJavaMemberName(column, Mode.POJO) // 4: strategy.getJavaSetterName(column, Mode.POJO) // 5: strategy.getJavaGetterName(column, Mode.POJO)
An out-of-the-box strategy to keep names as they are
By default, jOOQ's generator strategy will convert your database's UNDER_SCORE_NAMES
to PascalCaseNames
as this is a more common idiom in the Java ecosystem. If, however, you want to retain the names and the casing exactly as it is defined in your database, you can use the org.jooq.codegen.KeepNamesGeneratorStrategy
, which will retain all names exactly as they are.
More examples can be found here:
Feedback
Do you have any feedback about this page? We'd love to hear it!