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

JPADatabase: Code generation from entities

Applies to ✅ Open Source Edition   ✅ Express Edition   ✅ Professional Edition   ✅ Enterprise Edition

Many jOOQ users use jOOQ as a complementary SQL API in applications that mostly use JPA for their database interactions, e.g. to perform reporting, batch processing, analytics, etc.

In such a setup, you might have a pre-existing schema implemented using JPA-annotated entities. Your real database schema might not be accessible while developing, or it is not a first-class citizen in your application (i.e. you follow a Java-first approach). This section explains how you can generate jOOQ classes from such a JPA model. Consider this model:

@Entity
@Table(name = "author")
public class Author {

    @Id
    int       id;

    @Column(name = "first_name")
    String    firstName;

    @Column(name = "last_name")
    String    lastName;

    @OneToMany(mappedBy = "author")
    Set<Book> books;

    // Getters and setters...
}

@Entity
@Table(name = "book")
public class Book {

    @Id
    public int    id;

    @Column(name = "title")
    public String title;

    @ManyToOne
    public Author author;

    // Getters and setters...
}

Now, instead of connecting the jOOQ code generator to a database that holds a representation of the above schema, you can use jOOQ's JPADatabase and feed that to the code generator. The JPADatabase uses Hibernate internally, to generate an in-memory H2 database from your entities, and reverse-engineers that again back to jOOQ classes.

The easiest way forward is to use Maven in order to include the jooq-meta-extensions-hibernate library (which then includes the H2 and Hibernate dependencies)

Maven
Gradle (Kotlin)
Gradle (Groovy)
<dependency>
    <!-- Use org.jooq              for the Open Source Edition
             org.jooq.pro          for commercial editions with Java 11 support,
             org.jooq.pro-java-8   for commercial editions with Java 8 support,
             org.jooq.pro-java-6   for commercial editions with Java 6 support,
             org.jooq.trial        for the free trial edition with Java 11 support,
             org.jooq.trial-java-8 for the free trial edition with Java 8 support,
             org.jooq.trial-java-6 for the free trial edition with Java 6 support
    
     Note: Only the Open Source Edition is hosted on Maven Central.
           Install the others locally using the provided scripts, or access them from here: https://repo.jooq.org
           See the JDK version support matrix here: https://www.jooq.org/download/support-matrix-jdk -->

    <groupId>org.jooq</groupId>
    <artifactId>jooq-meta-extensions-hibernate</artifactId>
    <version>3.19.13</version>
</dependency>
dependencies {
    // Use org.jooq                for the Open Source Edition
    //     org.jooq.pro            for commercial editions with Java 17 support,
    //     org.jooq.pro-java-8     for commercial editions with Java 8 support,
    //     org.jooq.pro-java-6     for commercial editions with Java 6 support,
    //     org.jooq.trial          for the free trial edition with Java 17 support,
    //     org.jooq.trial-java-8   for the free trial edition with Java 8 support,
    //     org.jooq.trial-java-6   for the free trial edition with Java 6 support
    //
    // Note: Only the Open Source Edition is hosted on Maven Central.
    //       Install the others locally using the provided scripts, or access them from here: https://repo.jooq.org
    //       See the JDK version support matrix here: https://www.jooq.org/download/support-matrix-jdk

    implementation("org.jooq:jooq-meta-extensions-hibernate:3.19.13")
}
dependencies {
    // Use org.jooq                for the Open Source Edition
    //     org.jooq.pro            for commercial editions with Java 17 support,
    //     org.jooq.pro-java-8     for commercial editions with Java 8 support,
    //     org.jooq.pro-java-6     for commercial editions with Java 6 support,
    //     org.jooq.trial          for the free trial edition with Java 17 support,
    //     org.jooq.trial-java-8   for the free trial edition with Java 8 support,
    //     org.jooq.trial-java-6   for the free trial edition with Java 6 support
    //
    // Note: Only the Open Source Edition is hosted on Maven Central.
    //       Install the others locally using the provided scripts, or access them from here: https://repo.jooq.org
    //       See the JDK version support matrix here: https://www.jooq.org/download/support-matrix-jdk

    implementation "org.jooq:jooq-meta-extensions-hibernate:3.19.13"
}

With that dependency in place, you can now specify the JPADatabase in your code generator configuration:

XML (standalone and maven)
Programmatic
Gradle (Kotlin)
Gradle (Groovy)
Gradle (third party)
<configuration>
  <generator>
    <database>
      <name>org.jooq.meta.extensions.jpa.JPADatabase</name>
      <properties>

        <!-- A comma separated list of Java packages, that contain your entities -->
        <property>
          <key>packages</key>
          <value>com.example.entities</value>
        </property>

        <!-- Whether JPA 2.1 AttributeConverters should be auto-mapped to jOOQ Converters.
             Custom <forcedType/> configurations will have a higher priority than these auto-mapped converters.
             This defaults to true. -->
        <property>
          <key>useAttributeConverters</key>
          <value>true</value>
        </property>
        <!-- The default schema for unqualified objects:

             - public: all unqualified objects are located in the PUBLIC (upper case) schema
             - none: all unqualified objects are located in the default schema (default)

             This configuration can be overridden with the schema mapping feature -->
        <property>
          <key>unqualifiedSchema</key>
          <value>none</value>
        </property>
      </properties>
    </database>
  </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()
    .withDatabase(new Database()
      .withName("org.jooq.meta.extensions.jpa.JPADatabase")
      .withProperties(

        // A comma separated list of Java packages, that contain your entities
        new Property()
          .withKey("packages")
          .withValue("com.example.entities"),

        // Whether JPA 2.1 AttributeConverters should be auto-mapped to jOOQ Converters.
        // Custom <forcedType/> configurations will have a higher priority than these auto-mapped converters.
        // This defaults to true.
        new Property()
          .withKey("useAttributeConverters")
          .withValue(true),

        // The default schema for unqualified objects:
        // 
        // - public: all unqualified objects are located in the PUBLIC (upper case) schema
        // - none: all unqualified objects are located in the default schema (default)
        // 
        // This configuration can be overridden with the schema mapping feature
        new Property()
          .withKey("unqualifiedSchema")
          .withValue("none")
      )
    )
  )

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

import org.jooq.meta.jaxb.*


configuration {
  generator {
    database {
      name = "org.jooq.meta.extensions.jpa.JPADatabase"
      properties {

        // A comma separated list of Java packages, that contain your entities
        property {
          key = "packages"
          value = "com.example.entities"
        }

        // Whether JPA 2.1 AttributeConverters should be auto-mapped to jOOQ Converters.
        // Custom <forcedType/> configurations will have a higher priority than these auto-mapped converters.
        // This defaults to true.
        property {
          key = "useAttributeConverters"
          isValue = true
        }

        // The default schema for unqualified objects:
        // 
        // - public: all unqualified objects are located in the PUBLIC (upper case) schema
        // - none: all unqualified objects are located in the default schema (default)
        // 
        // This configuration can be overridden with the schema mapping feature
        property {
          key = "unqualifiedSchema"
          value = "none"
        }
      }
    }
  }
}

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

configuration {
  generator {
    database {
      name = "org.jooq.meta.extensions.jpa.JPADatabase"
      properties {

        // A comma separated list of Java packages, that contain your entities
        property {
          key = "packages"
          value = "com.example.entities"
        }

        // Whether JPA 2.1 AttributeConverters should be auto-mapped to jOOQ Converters.
        // Custom <forcedType/> configurations will have a higher priority than these auto-mapped converters.
        // This defaults to true.
        property {
          key = "useAttributeConverters"
          value = true
        }

        // The default schema for unqualified objects:
        // 
        // - public: all unqualified objects are located in the PUBLIC (upper case) schema
        // - none: all unqualified objects are located in the default schema (default)
        // 
        // This configuration can be overridden with the schema mapping feature
        property {
          key = "unqualifiedSchema"
          value = "none"
        }
      }
    }
  }
}

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

generationTool {
  generator {
    database {
      name = "org.jooq.meta.extensions.jpa.JPADatabase"
      properties {

        // A comma separated list of Java packages, that contain your entities
        property {
          key = "packages"
          value = "com.example.entities"
        }

        // Whether JPA 2.1 AttributeConverters should be auto-mapped to jOOQ Converters.
        // Custom <forcedType/> configurations will have a higher priority than these auto-mapped converters.
        // This defaults to true.
        property {
          key = "useAttributeConverters"
          value = true
        }

        // The default schema for unqualified objects:
        // 
        // - public: all unqualified objects are located in the PUBLIC (upper case) schema
        // - none: all unqualified objects are located in the default schema (default)
        // 
        // This configuration can be overridden with the schema mapping feature
        property {
          key = "unqualifiedSchema"
          value = "none"
        }
      }
    }
  }
}

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

The above will generate all jOOQ artefacts for your AUTHOR and BOOK tables.

Passing settings to Hibernate

The current versions of jOOQ use Hibernate behind the scenes to generate an in-memory H2 database from which to reverse engineer jOOQ code. In order to influence Hibernate's schema generation, Hibernate specific flags can be passed to MetadataSources. All properties that are prefixed with hibernate. or jakarta.persistence. will be passed along to Hibernate. For example, this is possible:

XML (standalone and maven)
Programmatic
Gradle (Kotlin)
Gradle (Groovy)
Gradle (third party)
<configuration>
  <generator>
    <database>
      <properties>
        <property>
          <key>hibernate.physical_naming_strategy</key>
          <value>org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy</value>
        </property>
      </properties>
    </database>
  </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()
    .withDatabase(new Database()
      .withProperties(
        new Property()
          .withKey("hibernate.physical_naming_strategy")
          .withValue("org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy")
      )
    )
  )

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

import org.jooq.meta.jaxb.*


configuration {
  generator {
    database {
      properties {
        property {
          key = "hibernate.physical_naming_strategy"
          value = "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy"
        }
      }
    }
  }
}

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

configuration {
  generator {
    database {
      properties {
        property {
          key = "hibernate.physical_naming_strategy"
          value = "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy"
        }
      }
    }
  }
}

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

generationTool {
  generator {
    database {
      properties {
        property {
          key = "hibernate.physical_naming_strategy"
          value = "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy"
        }
      }
    }
  }
}

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

How to organise your dependencies

The JPADatabase will use Spring to look up your annotated entities from the classpath. This means that you have to create several modules with a dependency graph that looks like this:

                        +-------------------+
                        | Your JPA entities |
                        +-------------------+
                             ^         ^
                  depends on |         | depends on
                             |         |
          +---------------------+   +---------------------+
          | jOOQ codegen plugin |   | Your application    |
          +---------------------+   +---------------------+
                             |         |
                   generates |         | depends on
                             v         v
                     +-------------------------+
                     | jOOQ generated classes  |
                     +-------------------------+

You cannot put your JPA entities in the same module as the one that runs the jOOQ code generator. See also code generator dependencies.

Feedback

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

The jOOQ Logo