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:
<configuration xmlns="http://www.jooq.org/xsd/jooq-codegen-3.14.0.xsd"> <generator> <database> <!-- Use regular expressions to match the domains that should be replaced by embeddables. --> <embeddableDomains>.*</embeddableDomains> </database> </generator> </configuration>
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(".*") ) )
myConfigurationName(sourceSets.main) { generator { database { // Use regular expressions to match the domains that should be replaced by embeddables. embeddableDomains = '.*' } } }
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!