@Column (jakarta.persistence)

The JPA @jakarta.persistence.Column provides metadata describing how JPA should persist the property to a database RDBMS table column (or equivalent concept for other persistence stores).

Apache Causeway also parses and interprets this annotation in order to build up aspects of its metamodel.

Apache Causeway parses the @Column annotation from the Java source code; it does not query the JPA metamodel. This means that it the @Column annotation must be used rather than XML metadata.

This section identifies which attributes of @Column are recognized and used by Apache Causeway.

Nullability

The nullable attribute is used to specify if a property is mandatory or is optional.

For example:

import jakarta.persistence.Column;

public class Customer {

    @Column(nullable=true)
    @Getter @Setter
    private String middleInitial;

    // ...
}

Causeway also provides @Property#optionality attribute. If both are specified, Apache Causeway will check when it initializes for any contradictions, and will fail-fast with an appropriate error message in the log if there are.

You should also be aware that in the lack of either the @Column#nullable or the @Property#optionality attributes, that the JPA/Eclipselink and Apache Causeway defaults differ. Apache Causeway rule is straight-forward: properties are assumed to be required. JPA/Eclipselink on the other hand properties are assumed to be optional. A lack of either annotation may result in a metamodel validation error.

In the vast majority of cases you should be fine just to add the @Column#nullable attribute to the getter. But see the documentation for @Property#optionality attribute for discussion on one or two minor edge cases.

Length for Strings

The length attribute is used to specify the length of java.lang.String property types as they map to varchar(n) columns.

For example:

import jakarta.persistence.Column;

public class Customer {

    @Column(length=20)
    @Getter @Setter
    private String firstName;

    @Column(length=1, nullable=true)
    @Getter @Setter
    private String middleInitial;

    @Column(length=30)
    @Getter @Setter
    private String lastName;

    // ...
}

Apache Causeway also provides @Property#maxLength attribute. If both are specified, Apache Causeway will check when it initializes for any contradictions, and will fail-fast with an appropriate error message in the log if there are.

Length/scale for BigDecimals

The length() and scale attributes are used to infer the precision/scale of java.math.BigDecimal property types as they map to decimal(n,p) columns.

For example:

import jakarta.persistence.Column;
import lombok.*;

public class Customer {

    @Column(length=10, scale=2)
    @Getter @Setter
    private BigDecimal totalOrdersToDate;

    //...
}

For BigDecimals it is also possible to specify the @Digits annotation, whose form is @Digits(integer, fraction). There is a subtle difference here: while @Column#scale() corresponds to @Digits#fraction(), the value of @Column#length() (ie the precision) is actually the sum of the @Digits’ `integer() and fraction() parts.

If both are specified, Apache Causeway will check when it initializes for any contradictions, and will fail-fast with an appropriate error message in the log if there are.

Hints and Tips

This seems to be a good place to describe some additional common mappings that use @Column. Unlike the sections above, the attributes specified in these hints and tips aren’t actually part of Apache Causeway metamodel.

Mapping foreign keys

The name attribute can be used to override the name of the column. References to other objects are generally mapped as foreign key columns. If there are multiple references to a given type, then you will want to override the name that JPA/Eclipselink would otherwise default.

For example:

import jakarta.persistence.Column;

public class PartyRelationship {

    @Column(name = "fromPartyId", nullable = false)
    @Getter @Setter
    private Party from;

    @Column(name = "toPartyId", nullable = false)
    @Getter @Setter
    private Party to;

    // ...
}

Mapping Blobs and Clobs

Causeway provides utility classes to help map Blobs and Clobs.

For example, here’s how to map a Blob:

@AttributeOverrides({
    @AttributeOverride(name="name",    column=@Column(name="attachment_name")),
    @AttributeOverride(name="mimeType",column=@Column(name="attachment_mimeType")),
    @AttributeOverride(name="bytes",   column=@Column(name="attachment_bytes"))
})
@Embedded
private BlobJpaEmbeddable attachment;

@Property()
@PropertyLayout()
public Blob getPdf() {
  return BlobJpaEmbeddable.toBlob(pdf);
}
public void setPdf(final Blob pdf) {
  this.pdf = BlobJpaEmbeddable.fromBlob(pdf);
}

And here’s how to map a Clob:

@AttributeOverrides({
    @AttributeOverride(name="name",    column=@Column(name="doc_name")),
    @AttributeOverride(name="mimeType",column=@Column(name="doc_mimeType")),
    @AttributeOverride(name="bytes",   column=@Column(name="doc_bytes"))
})
@Getter @Setter
private ClobJpaEmbeddable doc;

@Property()
@PropertyLayout()
public Clob getDoc() {
  return ClobJpaEmbeddable.toClob(doc);
}
public void setDoc(final Clob doc) {
  this.doc = ClobJpaEmbeddable.fromClob(doc);
}

See Also