Jakarta Persistence API provides a comprehensive framework for object-relational mapping, entity lifecycle management, and database operations in Java applications
Complete reference for entity annotations, relationship mappings, inheritance strategies, and mapping customizations in Jakarta Persistence.
import jakarta.persistence.*;Define entities that map Java classes to database tables.
/**
* Specifies that the class is an entity
* @since 1.0
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface Entity {
/**
* (Optional) The entity name. Defaults to the unqualified name of the entity class.
* This name is used to refer to the entity in queries.
*/
String name() default "";
}
/**
* Specifies the primary table for the annotated entity
* @since 1.0
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface Table {
/** (Optional) The name of the table */
String name() default "";
/** (Optional) The catalog of the table */
String catalog() default "";
/** (Optional) The schema of the table */
String schema() default "";
/** (Optional) Unique constraints to be placed on the table */
UniqueConstraint[] uniqueConstraints() default {};
/** (Optional) Indexes for the table */
Index[] indexes() default {};
}
/**
* Designates a class whose mapping information is applied to entities that inherit from it
* @since 1.0
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface MappedSuperclass {
}
/**
* Specifies that a class whose instances are stored as an intrinsic part of an owning entity
* @since 1.0
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface Embeddable {
}
/**
* Specifies that the property or field is not persistent
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Transient {
}Usage Example:
@Entity
@Table(name = "customers", schema = "sales")
public class Customer {
@Id
private Long id;
private String name;
}
@MappedSuperclass
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Version
private Integer version;
}
@Embeddable
public class Address {
private String street;
private String city;
private String zipCode;
}Define primary key fields and generation strategies.
/**
* Specifies the primary key of an entity
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Id {
}
/**
* Provides for the specification of generation strategies for primary keys
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface GeneratedValue {
/** (Optional) The primary key generation strategy */
GenerationType strategy() default GenerationType.AUTO;
/** (Optional) The name of the primary key generator */
String generator() default "";
}
/**
* Specifies a composite primary key class
* @since 1.0
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface IdClass {
/** The primary key class */
Class value();
}
/**
* Applied to a persistent field or property to denote a composite primary key
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface EmbeddedId {
}
/**
* Defines a primary key generator that may be referenced by name
* @since 1.0
*/
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface SequenceGenerator {
/** (Required) A unique generator name */
String name();
/** (Optional) The name of the database sequence object */
String sequenceName() default "";
/** (Optional) The catalog of the sequence generator */
String catalog() default "";
/** (Optional) The schema of the sequence generator */
String schema() default "";
/** (Optional) The value from which the sequence object is to start */
int initialValue() default 1;
/** (Optional) The amount to increment by when allocating sequence numbers */
int allocationSize() default 50;
}
/**
* Used to group SequenceGenerator annotations
* @since 2.2
*/
@Target({TYPE})
@Retention(RUNTIME)
public @interface SequenceGenerators {
/** Array of sequence generators */
SequenceGenerator[] value();
}
/**
* Defines a primary key generator using a database table
* @since 1.0
*/
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface TableGenerator {
/** (Required) A unique generator name */
String name();
/** (Optional) Name of table that stores the generated id values */
String table() default "";
/** (Optional) The catalog of the table */
String catalog() default "";
/** (Optional) The schema of the table */
String schema() default "";
/** (Optional) Name of the primary key column in the table */
String pkColumnName() default "";
/** (Optional) Name of the column that stores the generated id value */
String valueColumnName() default "";
/** (Optional) The primary key value in the generator table */
String pkColumnValue() default "";
/** (Optional) The initial value to be used */
int initialValue() default 0;
/** (Optional) The amount to increment by */
int allocationSize() default 50;
/** (Optional) Unique constraints on the table */
UniqueConstraint[] uniqueConstraints() default {};
/** (Optional) Indexes for the table */
Index[] indexes() default {};
}
/**
* Used to group TableGenerator annotations
* @since 2.2
*/
@Target({TYPE})
@Retention(RUNTIME)
public @interface TableGenerators {
/** Array of table generators */
TableGenerator[] value();
}Usage Example:
// Simple primary key
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
// Sequence generator
@Entity
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "order_seq")
@SequenceGenerator(name = "order_seq", sequenceName = "order_sequence", allocationSize = 10)
private Long id;
}
// Composite key with @IdClass
@Entity
@IdClass(OrderItemId.class)
public class OrderItem {
@Id
private Long orderId;
@Id
private Long productId;
private Integer quantity;
}
// Composite key with @EmbeddedId
@Entity
public class OrderItem {
@EmbeddedId
private OrderItemId id;
private Integer quantity;
}
@Embeddable
public class OrderItemId implements Serializable {
private Long orderId;
private Long productId;
}Map entity fields to database columns with detailed configuration.
/**
* Specifies the mapped column for a persistent property or field
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Column {
/** (Optional) The name of the column */
String name() default "";
/** (Optional) Whether the column is a unique key */
boolean unique() default false;
/** (Optional) Whether the database column is nullable */
boolean nullable() default true;
/** (Optional) Whether the column is included in SQL INSERT statements */
boolean insertable() default true;
/** (Optional) Whether the column is included in SQL UPDATE statements */
boolean updatable() default true;
/** (Optional) The SQL fragment to use when generating the DDL */
String columnDefinition() default "";
/** (Optional) The name of the table containing the column */
String table() default "";
/** (Optional) The column length (for String values) */
int length() default 255;
/** (Optional) The precision for a decimal column */
int precision() default 0;
/** (Optional) The scale for a decimal column */
int scale() default 0;
}
/**
* The simplest type of mapping to a database column
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Basic {
/** (Optional) Whether the value should be lazily fetched */
FetchType fetch() default FetchType.EAGER;
/** (Optional) Whether the value may be null */
boolean optional() default true;
}
/**
* Specifies that a persistent property or field should be persisted as a large object
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Lob {
}
/**
* Specifies that a persistent property or field should be persisted as an enumerated type
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Enumerated {
/** (Optional) The type used in mapping */
EnumType value() default EnumType.ORDINAL;
}
/**
* Must be specified for persistent fields or properties of type Date and Calendar
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Temporal {
/** (Required) The type used in mapping */
TemporalType value();
}
/**
* Specifies the version field or property for optimistic locking
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Version {
}Usage Example:
@Entity
public class Article {
@Id
@GeneratedValue
private Long id;
@Column(name = "title", nullable = false, length = 200)
private String title;
@Lob
@Column(name = "content")
private String content;
@Enumerated(EnumType.STRING)
@Column(length = 20)
private ArticleStatus status;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_at")
private Date createdAt;
@Column(precision = 10, scale = 2)
private BigDecimal price;
@Version
private Integer version;
}Embed objects as part of an entity.
/**
* Specifies a persistent field or property whose value is an embeddable instance
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface Embedded {
}
/**
* Used to override the mapping of a Basic property or field
* @since 1.0
*/
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface AttributeOverride {
/** (Required) The name of the property whose mapping is being overridden */
String name();
/** (Required) The column that is being mapped to the persistent attribute */
Column column();
}
/**
* Used to override mappings of multiple properties or fields
* @since 1.0
*/
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface AttributeOverrides {
/** Array of attribute overrides */
AttributeOverride[] value();
}
/**
* Used to override a mapping for an entity relationship
* @since 1.0
*/
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface AssociationOverride {
/** (Required) The name of the relationship property whose mapping is being overridden */
String name();
/** (Optional) The join columns that are used for the association */
JoinColumn[] joinColumns() default {};
/** (Optional) The foreign key constraint specification */
ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
/** (Optional) The join table that maps the relationship */
JoinTable joinTable() default @JoinTable;
}
/**
* Used to override mappings of multiple relationship properties or fields
* @since 1.0
*/
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface AssociationOverrides {
/** Array of association overrides */
AssociationOverride[] value();
}Usage Example:
@Embeddable
public class Address {
private String street;
private String city;
private String zipCode;
}
@Entity
public class Person {
@Id
private Long id;
@Embedded
private Address homeAddress;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "street", column = @Column(name = "work_street")),
@AttributeOverride(name = "city", column = @Column(name = "work_city")),
@AttributeOverride(name = "zipCode", column = @Column(name = "work_zip"))
})
private Address workAddress;
}Define relationships between entities.
/**
* Specifies a single-valued association to another entity with one-to-one multiplicity
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface OneToOne {
/** (Optional) The entity class that is the target of the association */
Class targetEntity() default void.class;
/** (Optional) The operations that must be cascaded to the target */
CascadeType[] cascade() default {};
/** (Optional) Whether the association should be lazily loaded or eagerly fetched */
FetchType fetch() default FetchType.EAGER;
/** (Optional) Whether the association is optional */
boolean optional() default true;
/** (Optional) The field that owns the relationship (bidirectional) */
String mappedBy() default "";
/** (Optional) Whether to apply the remove operation to orphaned entities */
boolean orphanRemoval() default false;
}
/**
* Specifies a many-valued association with one-to-many multiplicity
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface OneToMany {
/** (Optional) The entity class that is the target of the association */
Class targetEntity() default void.class;
/** (Optional) The operations that must be cascaded to the target */
CascadeType[] cascade() default {};
/** (Optional) Whether the association should be lazily loaded or eagerly fetched */
FetchType fetch() default FetchType.LAZY;
/** (Optional) The field that owns the relationship */
String mappedBy() default "";
/** (Optional) Whether to apply the remove operation to orphaned entities */
boolean orphanRemoval() default false;
}
/**
* Specifies a single-valued association to another entity with many-to-one multiplicity
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface ManyToOne {
/** (Optional) The entity class that is the target of the association */
Class targetEntity() default void.class;
/** (Optional) The operations that must be cascaded to the target */
CascadeType[] cascade() default {};
/** (Optional) Whether the association should be lazily loaded or eagerly fetched */
FetchType fetch() default FetchType.EAGER;
/** (Optional) Whether the association is optional */
boolean optional() default true;
}
/**
* Specifies a many-valued association with many-to-many multiplicity
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface ManyToMany {
/** (Optional) The entity class that is the target of the association */
Class targetEntity() default void.class;
/** (Optional) The operations that must be cascaded to the target */
CascadeType[] cascade() default {};
/** (Optional) Whether the association should be lazily loaded or eagerly fetched */
FetchType fetch() default FetchType.LAZY;
/** (Optional) The field that owns the relationship */
String mappedBy() default "";
}
/**
* Specifies a column for joining an entity association
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface JoinColumn {
/** (Optional) The name of the foreign key column */
String name() default "";
/** (Optional) The name of the column referenced by this foreign key column */
String referencedColumnName() default "";
/** (Optional) Whether the foreign key column is unique */
boolean unique() default false;
/** (Optional) Whether the foreign key column is nullable */
boolean nullable() default true;
/** (Optional) Whether the column is included in SQL INSERT statements */
boolean insertable() default true;
/** (Optional) Whether the column is included in SQL UPDATE statements */
boolean updatable() default true;
/** (Optional) The SQL fragment to use for the column definition */
String columnDefinition() default "";
/** (Optional) The name of the table containing the foreign key column */
String table() default "";
/** (Optional) The foreign key constraint specification */
ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
}
/**
* Specifies the mapping for composite foreign keys
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface JoinColumns {
/** Array of join columns */
JoinColumn[] value();
/** (Optional) The foreign key constraint specification */
ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
}
/**
* Specifies the mapping of associations
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface JoinTable {
/** (Optional) The name of the join table */
String name() default "";
/** (Optional) The catalog of the join table */
String catalog() default "";
/** (Optional) The schema of the join table */
String schema() default "";
/** (Optional) The foreign key columns of the join table */
JoinColumn[] joinColumns() default {};
/** (Optional) The foreign key columns of the join table (inverse side) */
JoinColumn[] inverseJoinColumns() default {};
/** (Optional) The foreign key constraint for join columns */
ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
/** (Optional) The foreign key constraint for inverse join columns */
ForeignKey inverseForeignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
/** (Optional) Unique constraints on the join table */
UniqueConstraint[] uniqueConstraints() default {};
/** (Optional) Indexes for the join table */
Index[] indexes() default {};
}
/**
* Designates a ManyToOne or OneToOne relationship attribute for an EmbeddedId primary key
* @since 2.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface MapsId {
/** (Optional) The name of the attribute within the composite key */
String value() default "";
}Usage Example:
// One-to-One
@Entity
public class User {
@Id
private Long id;
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "profile_id")
private UserProfile profile;
}
// One-to-Many / Many-to-One (bidirectional)
@Entity
public class Department {
@Id
private Long id;
@OneToMany(mappedBy = "department", cascade = CascadeType.ALL)
private List<Employee> employees = new ArrayList<>();
}
@Entity
public class Employee {
@Id
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id", nullable = false)
private Department department;
}
// Many-to-Many
@Entity
public class Student {
@Id
private Long id;
@ManyToMany
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
private Set<Course> courses = new HashSet<>();
}
@Entity
public class Course {
@Id
private Long id;
@ManyToMany(mappedBy = "courses")
private Set<Student> students = new HashSet<>();
}Map collections of basic types and embeddables.
/**
* Specifies a collection of instances of a basic type or embeddable class
* @since 2.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface ElementCollection {
/** (Optional) The basic or embeddable class that is the element type of the collection */
Class targetClass() default void.class;
/** (Optional) Whether the association should be lazily loaded or eagerly fetched */
FetchType fetch() default FetchType.LAZY;
}
/**
* Specifies the table that is used for the mapping of collections
* @since 2.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface CollectionTable {
/** (Optional) The name of the collection table */
String name() default "";
/** (Optional) The catalog of the table */
String catalog() default "";
/** (Optional) The schema of the table */
String schema() default "";
/** (Optional) The foreign key columns of the collection table */
JoinColumn[] joinColumns() default {};
/** (Optional) The foreign key constraint specification */
ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
/** (Optional) Unique constraints on the table */
UniqueConstraint[] uniqueConstraints() default {};
/** (Optional) Indexes for the table */
Index[] indexes() default {};
}
/**
* Specifies the ordering of collection elements
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface OrderBy {
/** (Optional) The ordering clause */
String value() default "";
}
/**
* Specifies a column that is used to maintain the persistent order of a list
* @since 2.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface OrderColumn {
/** (Optional) The name of the ordering column */
String name() default "";
/** (Optional) Whether the column is nullable */
boolean nullable() default true;
/** (Optional) Whether the column is included in SQL INSERT statements */
boolean insertable() default true;
/** (Optional) Whether the column is included in SQL UPDATE statements */
boolean updatable() default true;
/** (Optional) The SQL fragment for column definition */
String columnDefinition() default "";
}Usage Example:
@Entity
public class Person {
@Id
private Long id;
@ElementCollection
@CollectionTable(name = "phone_numbers", joinColumns = @JoinColumn(name = "person_id"))
@Column(name = "phone_number")
private Set<String> phoneNumbers = new HashSet<>();
@ElementCollection
@CollectionTable(name = "addresses")
@OrderColumn(name = "address_index")
private List<Address> addresses = new ArrayList<>();
}Map collections with custom keys.
/**
* Specifies the map key for associations of type Map
* @since 1.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface MapKey {
/** (Optional) The name of the persistent field or property of the map key */
String name() default "";
}
/**
* Specifies the type of the map key
* @since 2.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface MapKeyClass {
/** The type of the map key */
Class value();
}
/**
* Specifies the mapped column for the map key
* @since 2.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface MapKeyColumn {
/** (Optional) The name of the map key column */
String name() default "";
/** (Optional) Whether the column is unique */
boolean unique() default false;
/** (Optional) Whether the column is nullable */
boolean nullable() default false;
/** (Optional) Whether the column is insertable */
boolean insertable() default true;
/** (Optional) Whether the column is updatable */
boolean updatable() default true;
/** (Optional) The SQL fragment for column definition */
String columnDefinition() default "";
/** (Optional) The name of the table containing the column */
String table() default "";
/** (Optional) The column length */
int length() default 255;
/** (Optional) The precision for numeric columns */
int precision() default 0;
/** (Optional) The scale for numeric columns */
int scale() default 0;
}
/**
* Specifies the enum type for a map key
* @since 2.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface MapKeyEnumerated {
/** (Optional) The type used in mapping the map key enum */
EnumType value() default EnumType.ORDINAL;
}
/**
* Specifies the temporal type for a map key
* @since 2.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface MapKeyTemporal {
/** (Required) The temporal type for the map key */
TemporalType value();
}
/**
* Specifies a mapping to an entity that is a map key
* @since 2.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface MapKeyJoinColumn {
/** (Optional) The name of the foreign key column for the map key */
String name() default "";
/** (Optional) The name of the column referenced by this foreign key column */
String referencedColumnName() default "";
/** (Optional) Whether the column is unique */
boolean unique() default false;
/** (Optional) Whether the column is nullable */
boolean nullable() default false;
/** (Optional) Whether the column is insertable */
boolean insertable() default true;
/** (Optional) Whether the column is updatable */
boolean updatable() default true;
/** (Optional) The SQL fragment for column definition */
String columnDefinition() default "";
/** (Optional) The name of the table containing the column */
String table() default "";
/** (Optional) The foreign key constraint specification */
ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
}
/**
* Specifies the mapping for composite map key join columns
* @since 2.0
*/
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface MapKeyJoinColumns {
/** Array of map key join columns */
MapKeyJoinColumn[] value();
/** (Optional) The foreign key constraint specification */
ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
}Usage Example:
@Entity
public class Company {
@Id
private Long id;
@OneToMany
@MapKey(name = "employeeId")
private Map<String, Employee> employeesByNumber = new HashMap<>();
@ElementCollection
@MapKeyColumn(name = "department_name")
@Column(name = "budget")
private Map<String, BigDecimal> departmentBudgets = new HashMap<>();
}Map entity inheritance hierarchies to database tables.
/**
* Specifies the inheritance strategy for an entity class hierarchy
* @since 1.0
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface Inheritance {
/** (Optional) The strategy to use */
InheritanceType strategy() default InheritanceType.SINGLE_TABLE;
}
/**
* Specifies the discriminator column for SINGLE_TABLE and JOINED inheritance
* @since 1.0
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface DiscriminatorColumn {
/** (Optional) The name of the discriminator column */
String name() default "DTYPE";
/** (Optional) The type of object used to represent the discriminator column */
DiscriminatorType discriminatorType() default DiscriminatorType.STRING;
/** (Optional) The SQL fragment for column definition */
String columnDefinition() default "";
/** (Optional) The column length for STRING discriminator types */
int length() default 31;
}
/**
* Specifies the value of the discriminator column for entities of the given type
* @since 1.0
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface DiscriminatorValue {
/** (Required) The discriminator value */
String value();
}
/**
* Specifies a primary key column used as a foreign key to join to another table
* @since 1.0
*/
@Target({METHOD, FIELD, TYPE})
@Retention(RUNTIME)
public @interface PrimaryKeyJoinColumn {
/** (Optional) The name of the primary key column */
String name() default "";
/** (Optional) The name of the primary key column of the referenced table */
String referencedColumnName() default "";
/** (Optional) The SQL fragment for column definition */
String columnDefinition() default "";
/** (Optional) The foreign key constraint specification */
ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
}
/**
* Groups PrimaryKeyJoinColumn annotations for composite foreign keys
* @since 1.0
*/
@Target({TYPE})
@Retention(RUNTIME)
public @interface PrimaryKeyJoinColumns {
/** Array of primary key join columns */
PrimaryKeyJoinColumn[] value();
/** (Optional) The foreign key constraint specification */
ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
}Usage Example:
// Single table inheritance
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "vehicle_type", discriminatorType = DiscriminatorType.STRING)
public abstract class Vehicle {
@Id
private Long id;
private String manufacturer;
}
@Entity
@DiscriminatorValue("CAR")
public class Car extends Vehicle {
private Integer numberOfDoors;
}
@Entity
@DiscriminatorValue("TRUCK")
public class Truck extends Vehicle {
private BigDecimal payloadCapacity;
}
// Joined table inheritance
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Account {
@Id
private Long id;
private String accountNumber;
}
@Entity
@PrimaryKeyJoinColumn(name = "account_id")
public class SavingsAccount extends Account {
private BigDecimal interestRate;
}
@Entity
@PrimaryKeyJoinColumn(name = "account_id")
public class CheckingAccount extends Account {
private BigDecimal overdraftLimit;
}Map a single entity to multiple tables.
/**
* Specifies a secondary table for the annotated entity class
* @since 1.0
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface SecondaryTable {
/** (Required) The name of the secondary table */
String name();
/** (Optional) The catalog of the table */
String catalog() default "";
/** (Optional) The schema of the table */
String schema() default "";
/** (Optional) The columns that are used to join with the primary table */
PrimaryKeyJoinColumn[] pkJoinColumns() default {};
/** (Optional) The foreign key constraint specification */
ForeignKey foreignKey() default @ForeignKey(ConstraintMode.PROVIDER_DEFAULT);
/** (Optional) Unique constraints on the table */
UniqueConstraint[] uniqueConstraints() default {};
/** (Optional) Indexes for the table */
Index[] indexes() default {};
}
/**
* Specifies multiple secondary tables for an entity
* @since 1.0
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface SecondaryTables {
/** Array of secondary tables */
SecondaryTable[] value();
}Usage Example:
@Entity
@Table(name = "employee")
@SecondaryTable(name = "employee_details",
pkJoinColumns = @PrimaryKeyJoinColumn(name = "employee_id"))
public class Employee {
@Id
private Long id;
@Column(name = "name")
private String name;
@Column(table = "employee_details")
private String biography;
@Column(table = "employee_details")
private byte[] photo;
}Define database constraints and indexes.
/**
* Specifies that a unique constraint is to be included in the generated DDL
* @since 1.0
*/
@Target({})
@Retention(RUNTIME)
public @interface UniqueConstraint {
/** (Optional) Constraint name */
String name() default "";
/** (Required) An array of column names that make up the constraint */
String[] columnNames();
}
/**
* Used in schema generation to specify creation of an index
* @since 2.1
*/
@Target({})
@Retention(RUNTIME)
public @interface Index {
/** (Optional) The name of the index */
String name() default "";
/** (Required) The list of columns for the index */
String columnList();
/** (Optional) Whether the index is unique */
boolean unique() default false;
}
/**
* Used to specify the handling of foreign key constraints
* @since 2.1
*/
@Target({})
@Retention(RUNTIME)
public @interface ForeignKey {
/** (Optional) The name of the foreign key constraint */
String name() default "";
/** (Optional) The constraint mode */
ConstraintMode value() default ConstraintMode.PROVIDER_DEFAULT;
/** (Optional) The foreign key constraint definition */
String foreignKeyDefinition() default "";
}Specify field or property access for entities.
/**
* Used to specify an access type for an entity class, mapped superclass, or embeddable class
* @since 2.0
*/
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface Access {
/** (Required) The access type */
AccessType value();
}Usage Example:
@Entity
@Access(AccessType.FIELD)
public class Product {
@Id
private Long id;
private String name;
@Access(AccessType.PROPERTY)
@Column(name = "price")
public BigDecimal getPrice() {
return price.setScale(2, RoundingMode.HALF_UP);
}
public void setPrice(BigDecimal price) {
this.price = price;
}
private BigDecimal price;
}Convert entity attribute values to database column values.
/**
* Specifies the conversion of a Basic field or property
* @since 2.1
*/
@Target({METHOD, FIELD, TYPE})
@Retention(RUNTIME)
@Repeatable(Converts.class)
public @interface Convert {
/** (Optional) The converter class */
Class converter() default void.class;
/** (Optional) The name of the attribute to which the converter is applied */
String attributeName() default "";
/** (Optional) Whether to disable conversion */
boolean disableConversion() default false;
}
/**
* Used to group Convert annotations
* @since 2.1
*/
@Target({METHOD, FIELD, TYPE})
@Retention(RUNTIME)
public @interface Converts {
/** Array of converts */
Convert[] value();
}
/**
* Specifies that the annotated class is a converter
* @since 2.1
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface Converter {
/** (Optional) Whether the converter should be auto-applied */
boolean autoApply() default false;
}
/**
* Interface for entity attribute value conversion
* @since 2.1
*/
public interface AttributeConverter<X, Y> {
/**
* Converts the entity attribute value to database column value
* @param attribute the entity attribute value
* @return the database column value
*/
Y convertToDatabaseColumn(X attribute);
/**
* Converts the database column value to entity attribute value
* @param dbData the database column value
* @return the entity attribute value
*/
X convertToEntityAttribute(Y dbData);
}Usage Example:
@Converter(autoApply = true)
public class BooleanToYNConverter implements AttributeConverter<Boolean, String> {
@Override
public String convertToDatabaseColumn(Boolean attribute) {
return attribute != null && attribute ? "Y" : "N";
}
@Override
public Boolean convertToEntityAttribute(String dbData) {
return "Y".equals(dbData);
}
}
@Entity
public class Customer {
@Id
private Long id;
@Convert(converter = BooleanToYNConverter.class)
private Boolean active;
}Define named entity graphs for optimizing fetch strategies and controlling which associations should be loaded.
/**
* Used to specify the path and boundaries for a find operation or query
* @since 2.1
*/
@Repeatable(NamedEntityGraphs.class)
@Target(TYPE)
@Retention(RUNTIME)
public @interface NamedEntityGraph {
/**
* (Optional) The name of the entity graph. Defaults to the entity name of the root entity
*/
String name() default "";
/**
* A list of attributes of the entity that are included in this graph
*/
NamedAttributeNode[] attributeNodes() default {};
/**
* Include all of the attributes of the annotated entity class as attribute nodes
*/
boolean includeAllAttributes() default false;
/**
* A list of subgraphs that are included in the entity graph
*/
NamedSubgraph[] subgraphs() default {};
/**
* A list of subgraphs that will add additional attributes for subclasses
*/
NamedSubgraph[] subclassSubgraphs() default {};
}
/**
* Used to group NamedEntityGraph annotations
* @since 2.1
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface NamedEntityGraphs {
/** Array of NamedEntityGraph annotations */
NamedEntityGraph[] value();
}
/**
* A member element of a NamedEntityGraph
* @since 2.1
*/
@Target({})
@Retention(RUNTIME)
public @interface NamedAttributeNode {
/**
* The name of the attribute that must be included in the graph
*/
String value();
/**
* If the attribute references a managed type, refer to that NamedSubgraph definition
*/
String subgraph() default "";
/**
* If the attribute references a Map, specify a subgraph for the Entity key type
*/
String keySubgraph() default "";
}
/**
* A member element of a NamedEntityGraph, referenced from NamedAttributeNode
* @since 2.1
*/
@Target({})
@Retention(RUNTIME)
public @interface NamedSubgraph {
/**
* The name of the subgraph as referenced from a NamedAttributeNode element
*/
String name();
/**
* The type represented by this subgraph
*/
Class type() default void.class;
/**
* The list of attributes of the class that must be included
*/
NamedAttributeNode[] attributeNodes();
}Usage Example:
@Entity
@NamedEntityGraph(
name = "Order.detail",
attributeNodes = {
@NamedAttributeNode("customer"),
@NamedAttributeNode(value = "items", subgraph = "items.detail")
},
subgraphs = {
@NamedSubgraph(
name = "items.detail",
attributeNodes = {
@NamedAttributeNode("product"),
@NamedAttributeNode("quantity")
}
)
}
)
public class Order {
@Id
private Long id;
@ManyToOne
private Customer customer;
@OneToMany
private List<OrderItem> items;
}
// Use the entity graph
EntityGraph<?> graph = em.getEntityGraph("Order.detail");
Map<String, Object> props = new HashMap<>();
props.put("jakarta.persistence.fetchgraph", graph);
Order order = em.find(Order.class, orderId, props);Annotations for dependency injection of persistence contexts and entity manager factories in Jakarta EE containers.
/**
* Expresses a dependency on a container-managed EntityManager
* @since 1.0
*/
@Repeatable(PersistenceContexts.class)
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface PersistenceContext {
/**
* (Optional) The name by which the entity manager is to be accessed
*/
String name() default "";
/**
* (Optional) The name of the persistence unit as defined in persistence.xml
*/
String unitName() default "";
/**
* (Optional) Specifies whether a transaction-scoped or extended persistence context is used
*/
PersistenceContextType type() default PersistenceContextType.TRANSACTION;
/**
* (Optional) Specifies whether the persistence context is automatically synchronized
* @since 2.1
*/
SynchronizationType synchronization() default SynchronizationType.SYNCHRONIZED;
/**
* (Optional) Properties for the container or persistence provider
*/
PersistenceProperty[] properties() default {};
}
/**
* Declares one or more PersistenceContext annotations
* @since 1.0
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface PersistenceContexts {
/** One or more PersistenceContext annotations */
PersistenceContext[] value();
}
/**
* Expresses a dependency on an EntityManagerFactory
* @since 1.0
*/
@Repeatable(PersistenceUnits.class)
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface PersistenceUnit {
/**
* (Optional) The name by which the entity manager factory is to be accessed
*/
String name() default "";
/**
* (Optional) The name of the persistence unit as defined in persistence.xml
*/
String unitName() default "";
}
/**
* Declares one or more PersistenceUnit annotations
* @since 1.0
*/
@Target(TYPE)
@Retention(RUNTIME)
public @interface PersistenceUnits {
/** One or more PersistenceUnit annotations */
PersistenceUnit[] value();
}
/**
* Describes a single container or persistence provider property
* @since 1.0
*/
@Target({})
@Retention(RUNTIME)
public @interface PersistenceProperty {
/** The name of the property */
String name();
/** The value of the property */
String value();
}Usage Example:
@Stateless
public class OrderService {
// Inject EntityManager
@PersistenceContext(unitName = "orderDB")
private EntityManager em;
// Inject EntityManagerFactory
@PersistenceUnit(unitName = "orderDB")
private EntityManagerFactory emf;
// With properties
@PersistenceContext(
unitName = "orderDB",
type = PersistenceContextType.EXTENDED,
properties = {
@PersistenceProperty(name = "jakarta.persistence.cache.storeMode", value = "REFRESH")
}
)
private EntityManager extendedEm;
public void processOrder(Long orderId) {
Order order = em.find(Order.class, orderId);
// Process order
}
}Install with Tessl CLI
npx tessl i tessl/maven-jakarta-persistence--jakarta-persistence-api