New versions: Dev (3.15) | Latest (3.14)

Configuration

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

Embeddable types can be specified in the code generator configuration as follows:

XML (standalone and maven)
Programmatic
Gradle
<configuration xmlns="http://www.jooq.org/xsd/jooq-codegen-3.14.0.xsd">
  <generator>
    <database>
    
      <!-- For each type, one embeddable entry is required -->
      <embeddables>
        <embeddable>
        
          <!-- The optional catalog of the embeddable type (the catalog of the first matched table if left empty) -->
          <catalog/>
          
          <!-- The optional schema of the embeddable type (the schema of the first matched table if left empty) -->
          <schema>PUBLIC</schema>
        
          <!-- The name of the embeddable type -->
          <name>AUDIT</name>
          
          <!-- An optional, defining comment of an embeddable -->
          <comment>An audit record containing common audit fields.</comment>
          
          <!-- The name of the reference to the embeddable type. Defaults to <name/> if left blank -->
          <referencingName>AUDIT_REFERENCE</referencingName>      
          
          <!-- An optional, referencing comment of an embeddable. Defaults to <comment/> if left blank -->
          <referencingComment>An audit record containing common audit fields.</referencingComment>
          
          <!-- A regular expression matching qualified or unqualified table names to which to apply this embeddable specification
               If left blank, this will apply to all tables -->
          <tables>.*</tables>
          
          <!-- A list of fields to match to an embeddable's attributes. Each field must match exactly one column in each matched table.
               A mandatory regular expression matches field names, whereas an optional name can be provided to define the embeddable
               attribute name. If no name is provided, then the first matched field's name will be taken -->
          <fields>
            <field><expression>CREATED_AT</expression></field>
            <field><expression>CREATED_BY</expression></field>
            <field><name>MODIFIED_AT</name><expression>MODIFIED_AT|CHANGED_AT</expression></field>
            <field><name>MODIFIED_BY</name><expression>MODIFIED_BY|CHANGED_BY</expression></field>
          </fields>
        </embeddable>
        
        <!-- A more minimal configuration might look like this -->
        <embeddable>
          <name>MONETARY_AMOUNT</name>
          <fields>
            <field><expression>AMOUNT</expression></field>
            <field><expression>CURRENCY</expression></field>
          </fields>
        </embeddable>
      </embeddables>
    </database>
  </generator>
</configuration>
new org.jooq.meta.jaxb.Configuration()
  .withGenerator(new Generator()
    .withDatabase(new Database()

      // For each type, one embeddable entry is required
      .withEmbeddables(
        new EmbeddableDefinitionType()

          // The optional catalog of the embeddable type (the catalog of the first matched table if left empty)
          .withCatalog("")

          // The optional schema of the embeddable type (the schema of the first matched table if left empty)
          .withSchema("PUBLIC")

          // The name of the embeddable type
          .withName("AUDIT")

          // An optional, defining comment of an embeddable
          .withComment("An audit record containing common audit fields.")

          // The name of the reference to the embeddable type. Defaults to <name/> if left blank
          .withReferencingName("AUDIT_REFERENCE")

          // An optional, referencing comment of an embeddable. Defaults to <comment/> if left blank
          .withReferencingComment("An audit record containing common audit fields.")

          // A regular expression matching qualified or unqualified table names to which to apply this embeddable specification
          // If left blank, this will apply to all tables
          .withTables(".*")

          // A list of fields to match to an embeddable's attributes. Each field must match exactly one column in each matched table.
          // A mandatory regular expression matches field names, whereas an optional name can be provided to define the embeddable
          // attribute name. If no name is provided, then the first matched field's name will be taken
          .withFields(
            new EmbeddableField()
              .withExpression("CREATED_AT"),
            new EmbeddableField()
              .withExpression("CREATED_BY"),
            new EmbeddableField()
              .withName("MODIFIED_AT")
              .withExpression("MODIFIED_AT|CHANGED_AT"),
            new EmbeddableField()
              .withName("MODIFIED_BY")
              .withExpression("MODIFIED_BY|CHANGED_BY")
          ),

        // A more minimal configuration might look like this
        new EmbeddableDefinitionType()
          .withName("MONETARY_AMOUNT")
          .withFields(
            new EmbeddableField()
              .withExpression("AMOUNT"),
            new EmbeddableField()
              .withExpression("CURRENCY")
          )
      )
    )
  )
myConfigurationName(sourceSets.main) {
  generator {
    database {

      // For each type, one embeddable entry is required
      embeddables {
        embeddable {

          // The optional catalog of the embeddable type (the catalog of the first matched table if left empty)
          catalog {}

          // The optional schema of the embeddable type (the schema of the first matched table if left empty)
          schema = 'PUBLIC'

          // The name of the embeddable type
          name = 'AUDIT'

          // An optional, defining comment of an embeddable
          comment = 'An audit record containing common audit fields.'

          // The name of the reference to the embeddable type. Defaults to <name/> if left blank
          referencingName = 'AUDIT_REFERENCE'

          // An optional, referencing comment of an embeddable. Defaults to <comment/> if left blank
          referencingComment = 'An audit record containing common audit fields.'

          // A regular expression matching qualified or unqualified table names to which to apply this embeddable specification
          // If left blank, this will apply to all tables
          tables = '.*'

          // A list of fields to match to an embeddable's attributes. Each field must match exactly one column in each matched table.
          // A mandatory regular expression matches field names, whereas an optional name can be provided to define the embeddable
          // attribute name. If no name is provided, then the first matched field's name will be taken
          fields {
            field {
              expression = 'CREATED_AT'
            }
            field {
              expression = 'CREATED_BY'
            }
            field {
              name = 'MODIFIED_AT'
              expression = 'MODIFIED_AT|CHANGED_AT'
            }
            field {
              name = 'MODIFIED_BY'
              expression = 'MODIFIED_BY|CHANGED_BY'
            }
          }
        }

        // A more minimal configuration might look like this
        embeddable {
          name = 'MONETARY_AMOUNT'
          fields {
            field {
              expression = 'AMOUNT'
            }
            field {
              expression = 'CURRENCY'
            }
          }
        }
      }
    }
  }
}

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

The previous configuration, if matched correctly against relevant tables, produces the following org.jooq.EmbeddableRecord implementations (abbreviated):

public class AuditRecord extends EmbeddableRecordImpl<AuditRecord> {
    public AuditRecord(Timestamp createdAt, Timestamp modifiedAt, String createdBy, String modifiedBy) { /* ... */ }
    
    // Getters, setters
}
public class MonetaryAmountRecord extends EmbeddableRecordImpl<MonetaryAmountRecord> {
    public MonetaryAmountRecord(BigDecimal amount, String currency) { /* ... */ }
    
    // Getters, setters
}

Assuming we have a TRANSACTIONS table like this:

CREATE TABLE transactions (
  id BIGINT NOT NULL PRIMARY KEY,
  created_at TIMESTAMP NOT NULL,
  modified_at TIMESTAMP,
  created_by VARCHAR(100) NOT NULL,
  modified_by VARCHAR(100) NOT NULL,
  
  -- Other columns here
  amount DECIMAL(18, 2) NOT NULL,
  currency VARCHAR(10) NOT NULL
);

With the previous embeddable type definitions, we would get a table that looks like this:

public class Transactions extends TableImpl<TransactionsRecord> {
    // Field initialisations omitted for simplicity
    
    // The AUDIT embeddable and its physical fields that it represents 
    public TableField<TransactionsRecord, Integer> ID;
    public TableField<TransactionsRecord, Timestamp> CREATED_AT;
    public TableField<TransactionsRecord, Timestamp> MODIFIED_AT;
    public TableField<TransactionsRecord, String> CREATED_BY;
    public TableField<TransactionsRecord, String> MODIFIED_BY;
    public TableField<TransactionsRecord, AuditRecord> AUDIT_REFERENCE;
    
    // The MONETARY_AMOUNT embeddable and its physical fields that it represents 
    public TableField<TransactionsRecord, BigDecimal> AMOUNT;
    public TableField<DRecord, String> CURRENCY;
    public TableField<DRecord, MonetaryAmountRecord> MONETARY_AMOUNT;

Notice how the embeddable type is just an auxiliary column, which, by default, does not replace its underlying columns. In order to replace the underlying columns, use the <replaceFields/> flag

You can now work with the underlying columns, as always, or use the embeddable types instead:

create.insertInto(TRANSACTIONS)
      .columns(TRANSACTIONS.ID, TRANSACTIONS.AUDIT_REFERENCE, TRANSACTIONS.MONETARY_AMOUNT)
      .values(
            1,
            new AuditRecord(Timestamp.valueOf("2000-01-01 00:00:00"), null, "user", null),
            new MonetaryAmountRecord(new BigDecimal("20.00"), "EUR"))
      .execute();

These columns can be used in all types of statements, including e.g. SELECT, INSERT, UPDATE, DELETE

Feedback

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

The jOOQ Logo