Available in versions: Dev (3.18) | Latest (3.17) | 3.16 | 3.15 | 3.14

Embedded domains

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

A very useful application of embeddable types are DOMAIN types. A DOMAIN type is a combination of:

  • A semantic type name
  • A data type (or other domain type)
  • A default value
  • A CHECK constraint

The combination name/type is enough to describe a semantic type like EMAIL across your schema, much better than e.g. VARCHAR(10). With embedded domains, you can generate a Java type for each domain type, and have that automatically attached to all your columns.

You can turn on the feature like this:

XML (standalone and maven)
Programmatic
Gradle
<configuration>
  <generator>
    <database>

      <!-- Use regular expressions to match the domains that should be replaced by embeddables. -->
      <embeddableDomains>.*</embeddableDomains>
    </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()

      // Use regular expressions to match the domains that should be replaced by embeddables.
      .withEmbeddableDomains(".*")
    )
  )

See the configuration XSD andprogrammatic code generation for more details.

myConfigurationName(sourceSets.main) {
  generator {
    database {

      // Use regular expressions to match the domains that should be replaced by embeddables.
      embeddableDomains = '.*'
    }
  }
}

See the configuration XSD andgradle code generation for more details.

As always, when regular expressions are used, they are regular expressions with default flags.

This will automatically produce an embeddable type configuration for each DOMAIN. For example, this schema:

CREATE DOMAIN email AS varchar(100);
CREATE DOMAIN year AS int;

CREATE TABLE user (
  id bigint NOT NULL PRIMARY KEY,
  name varchar(100) NOT NULL,
  email email NOT NULL,
  created year NOT NULL
);

The above would generate the following set of classes (simplified):

public class EmailRecord extends EmbeddableRecordImpl<EmailRecord> {
    public void setValue(String value) { ... }
    public String getValue() { ... }
    public EmailRecord() { ... }
    public EmailRecord(String value) { ... }
}

public class YearRecord extends EmbeddableRecordImpl<YearRecord> {
    public void setValue(Integer value) { ... }
    public Integer getValue() { ... }
    public YearRecord() { ... }
    public YearRecord(Integer value) { ... }
}

These classes are now referenced by embedded fields in the User table and UserRecord record (simplified):

public class User extends TableImpl<UserRecord> {
    public final TableField<UserRecord, Integer> ID;
    public final TableField<UserRecord, String> NAME;
    public final TableField<UserRecord, EmailRecord> EMAIL;
    public final TableField<UserRecord, YearRecord> CREATED;
}

With these generated fields, you can create semantically type safe queries:

create.insertInto(USER)
      .columns(USER.ID, USER.NAME, USER.EMAIL, USER.CREATED)
      .values(1, "domain_user", new EmailRecord("domain@user.com"), new YearRecord(2020))
      .execute();

Feedback

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

The jOOQ Logo