Available in versions: Dev (3.22)

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.

Reducing the size of generated code

Supported by ✅ Open Source Edition   ✅ Express Edition   ✅ Professional Edition   ✅ Enterprise Edition

jOOQ's generated code contains a lot of convenience, much of which is optional. For most schemas, this is not a problem, but for very large schemas with thousands of tables, foreign keys, or routines, the sheer amount of generated code can become a burden:

  • Compilation (javac, kotlinc, scalac) gets slow and may require a lot of memory, especially with complex generic types
  • IDEs need more time and memory to index the generated sources
  • The resulting artefacts get larger, and class loading at runtime takes longer

While the section about code generation for large schemas deals with hard limits of the compiler and the JVM, this section summarises the code generation flags that can be used to reduce the overall size of generated code, and the functionality that you give up when doing so. Typically, you will want to turn off only those features that you don't need in your project.

Generate fewer objects

The most effective way of reducing the size of generated code is not to generate objects that you don't need at all:

  • Use <includes/> and <excludes/> to restrict code generation to the tables, routines, etc. that your application actually uses. This includes excluding backup tables, staging tables, legacy objects, etc.
  • Use the include object types flags (e.g. <includeRoutines/>, <includePackages/>, <includeUDTs/>, <includeSequences/>, <includeIndexes/>, <includeCheckConstraints/>) to exclude entire object types. Indexes and check constraints, for example, are only needed if you use the generated meta data, e.g. to generate DDL.
  • Keep the <includeSystemTables/>, <includeSystemIndexes/>, <includeSystemSequences/>, etc. flags turned off (which is the default).
  • Turn off global object references such as <globalObjectReferences/>, if you always dereference objects from their schema or table classes, rather than from the generated Tables, Keys, Indexes, Routines, etc. classes.

Optional artefacts that are turned off by default

A few flags are turned off by default, but may have been enabled in your configuration (e.g. because they used to be turned on by default in older versions of jOOQ). Revisit these if code size is a concern:

  • <recordsImplementingRecordN/>: Makes generated records implement Record1<T1> to Record22<T1, ..., T22> and generates a lot of additional methods on records and tables, including fieldsRow(), valuesRow(), value1() to value22(), values(...), and type safe mapping() methods. The many generic type parameters are particularly heavy for compilers. Without this, you can still use records in the same way, except that the degree and column types are not available to the compiler on the record type.
  • <implicitJoinPathUnusedConstructors/>: Generates path constructors on tables that aren't involved in any foreign key relationship. This is rarely needed.
  • <pojos/>, <interfaces/>, <daos/>: Each of these generates an additional class per table (and UDT). If you need them only for some tables, use <pojosIncludes/>, <pojosExcludes/>, <daosIncludes/>, and <daosExcludes/> to restrict their generation. Note that DAOs also require records to be generated.
  • <fluentSetters/>, <varargSetters/>, <explicitNullability/> (see explicit nullability): These generate additional methods or code per column.
  • Annotations, including <generatedAnnotation/>, <jpaAnnotations/>, <validationAnnotations/>, <nonnullAnnotation/>, <nullableAnnotation/>, <constructorPropertiesAnnotation/> (see the section about annotations).

Records

Generated records (<records/>) are mainly needed for CRUD with UpdatableRecords, and to get a type safe TableRecord type when fetching from a single table. If records are turned off, generated tables reference org.jooq.Record as their record type, instead.

If you need records only for some tables, e.g. those that you use with CRUD or DAOs, use <recordsIncludes/> and <recordsExcludes/> to generate records only for those tables.

Implicit join paths

For every foreign key, the code generator produces implicit join path constructors (methods and possibly cached instances) on both the referencing and the referenced table. In schemas with many foreign keys, this can add up to a significant amount of code. The relevant flags are:

  • <implicitJoinPathsToOne/>: Path constructors for outgoing foreign keys (to-one relationships), e.g. BOOK.author()
  • <implicitJoinPathsToMany/>: Path constructors for incoming foreign keys (to-many relationships), e.g. AUTHOR.book()
  • <implicitJoinPathsManyToMany/>: Path constructors for many-to-many relationships via relationship tables. These are turned off implicitly if either of the above is turned off.
  • <implicitJoinPathTableSubtypes/>: A Path subtype per table (e.g. AuthorPath) that implements org.jooq.Path. Without these subtypes, path constructors return the ordinary generated table type, and features that depend on the Path type, such as path joins with an optional ON clause (e.g. .join(BOOK.author())), are unavailable.

All of these are mere convenience. When turned off, you can no longer use implicit path joins or path correlation, but you can still write explicit joins, including joins using ON KEY, which only depend on the generated keys (<relations/>).

Covariant overrides

Each generated table overrides a set of methods from org.jooq.Table to return the generated table type instead of the general Table<R> type (see covariant overrides):

  • <whereMethodOverrides/>: About 10 overloads of where(), whereExists() and whereNotExists(), to support inline derived tables. These can usually be turned off without much loss.
  • <renameMethodOverrides/>: Overloads of rename(). These can usually be turned off without much loss.
  • <asMethodOverrides/>: Overloads of as(). Turning these off has a significant impact on usability, as aliased tables can no longer dereference their columns in a type safe way (e.g. a.FIRST_NAME), but only via a.field(AUTHOR.FIRST_NAME). It is usually better to leave these turned on.

Javadoc, comments, and sources

  • <javadoc/> and <comments/> (and the more fine grained <commentsOnXYZ/> flags): Javadoc doesn't contribute to byte code, but it makes source files larger, which affects compilation, IDE indexing, and version control (see comments).
  • <sources/> and <sourcesOnViews/>: The source code of views is generated as a string literal into the generated table class. For large views, these literals can be quite large (see sources).

Other flags

  • <deprecated/>: Turn off the generation of deprecated code that is only kept for backwards compatibility.
  • <udtPaths/> and <embeddablePaths/>: Turn off the generation of path expressions for UDT attributes and embeddable fields on tables, if you don't dereference nested attributes or fields in your queries.
  • <indexes/> and <sequenceFlags/>: Index and sequence flag meta data is only needed if you work with the generated meta data, e.g. to export DDL.
  • <relations/>: As a last resort, primary keys, unique keys, and foreign keys can be turned off. This is not recommended, as a lot of functionality depends on them, including UpdatableRecord CRUD, ON KEY joins, and all implicit join paths.

Example

The following configuration turns off all of the convenience features that can be turned off without losing too much essential functionality:

XML (standalone and maven)
Programmatic
Gradle (Kotlin)
Gradle (Groovy)
Gradle (third party)
<configuration>
  <generator>
    <generate>

      <!-- Keep these turned off (the default) -->
      <recordsImplementingRecordN>false</recordsImplementingRecordN>
      <implicitJoinPathUnusedConstructors>false</implicitJoinPathUnusedConstructors>

      <!-- Generate records only where CRUD is needed -->
      <records>true</records>
      <recordsIncludes>CUSTOMER|ORDER|ORDER_LINE</recordsIncludes>

      <!-- Turn off implicit join path convenience -->
      <implicitJoinPathsToOne>false</implicitJoinPathsToOne>
      <implicitJoinPathsToMany>false</implicitJoinPathsToMany>
      <implicitJoinPathsManyToMany>false</implicitJoinPathsManyToMany>
      <implicitJoinPathTableSubtypes>false</implicitJoinPathTableSubtypes>

      <!-- Turn off rarely used covariant overrides -->
      <whereMethodOverrides>false</whereMethodOverrides>
      <renameMethodOverrides>false</renameMethodOverrides>

      <!-- Turn off additional documentation and sources -->
      <comments>false</comments>
      <sourcesOnViews>false</sourcesOnViews>
      <deprecated>false</deprecated>
    </generate>
  </generator>
</configuration>

See the configuration XSD, standalone code generation, and maven code generation for more details.

new org.jooq.meta.jaxb.Configuration()
  .withGenerator(
    new Generate()

      // Keep these turned off (the default)
      .withRecordsImplementingRecordN(false)
      .withImplicitJoinPathUnusedConstructors(false)

      // Generate records only where CRUD is needed
      .withRecords(true)
      .withRecordsIncludes("CUSTOMER|ORDER|ORDER_LINE")

      // Turn off implicit join path convenience
      .withImplicitJoinPathsToOne(false)
      .withImplicitJoinPathsToMany(false)
      .withImplicitJoinPathsManyToMany(false)
      .withImplicitJoinPathTableSubtypes(false)

      // Turn off rarely used covariant overrides
      .withWhereMethodOverrides(false)
      .withRenameMethodOverrides(false)

      // Turn off additional documentation and sources
      .withComments(false)
      .withSourcesOnViews(false)
      .withDeprecated(false)
  )

See the configuration XSD and programmatic code generation for more details.

import org.jooq.meta.jaxb.*


configuration {
  generator {
    generate {

      // Keep these turned off (the default)
      isRecordsImplementingRecordN = false
      isImplicitJoinPathUnusedConstructors = false

      // Generate records only where CRUD is needed
      isRecords = true
      recordsIncludes = "CUSTOMER|ORDER|ORDER_LINE"

      // Turn off implicit join path convenience
      isImplicitJoinPathsToOne = false
      isImplicitJoinPathsToMany = false
      isImplicitJoinPathsManyToMany = false
      isImplicitJoinPathTableSubtypes = false

      // Turn off rarely used covariant overrides
      isWhereMethodOverrides = false
      isRenameMethodOverrides = false

      // Turn off additional documentation and sources
      isComments = false
      isSourcesOnViews = false
      isDeprecated = false
    }
  }
}

See the configuration XSD and gradle code generation for more details.

configuration {
  generator {
    generate {

      // Keep these turned off (the default)
      recordsImplementingRecordN = false
      implicitJoinPathUnusedConstructors = false

      // Generate records only where CRUD is needed
      records = true
      recordsIncludes = "CUSTOMER|ORDER|ORDER_LINE"

      // Turn off implicit join path convenience
      implicitJoinPathsToOne = false
      implicitJoinPathsToMany = false
      implicitJoinPathsManyToMany = false
      implicitJoinPathTableSubtypes = false

      // Turn off rarely used covariant overrides
      whereMethodOverrides = false
      renameMethodOverrides = false

      // Turn off additional documentation and sources
      comments = false
      sourcesOnViews = false
      deprecated = false
    }
  }
}

See the configuration XSD and gradle code generation for more details.

// The jOOQ-codegen-gradle plugin has been introduced in version 3.19.
// Please use the official plugin instead of the third party plugin that was recommended before.

Whether turning off any of these flags helps depends on your schema and your build. It is advisable to measure compilation time and memory consumption of your build before and after such changes, and to turn off only those features that make a noticeable difference.

Feedback

Do you have any feedback about this page? We'd love to hear it!

The jOOQ Logo