Entities
An entity is a lightweight persistence domain object. Typically an entity represents a table in a relational database, and each entity instance corresponds to a row in that table. The primary programming artifact of an entity is the entity class, although entities can use helper classes.
The persistent state of an entity is represented either through persistent fields or persistent properties. These fields or properties use object/relational mapping annotations to map the entities and entity relationships to the relational data in the underlying data store.
Requirements for Entity Classes
An entity class must follow these requirements:
- The class must be annotated with the
javax.persistence.Entity
annotation.- The class must have a public or protected, no-argument constructor. The class may have other constructors.
- The class must not be declared
final
. No methods or persistent instance variables must be declaredfinal
.- If an entity instance be passed by value as a detached object, such as through a session bean's remote business interface, the class must implement the
Serializable
interface.- Entities may extend both entity and non-entity classes, and non-entity classes may extend entity classes.
- Persistent instance variables must be declared private, protected, or package-private, and can only be accessed directly by the entity class's methods. Clients must access the entity's state through accessor or business methods.
Persistent Fields and Properties in Entity Classes
The persistent state of an entity can be accessed either through the entity's instance variables or through JavaBeans-style properties. The fields or properties must be of the following Java language types:
Entities may either use persistent fields or persistent properties. If the mapping annotations are applied to the entity's instance variables, the entity uses persistent fields. If the mapping annotations are applied to the entity's getter methods for JavaBeans-style properties, the entity uses persistent properties. You cannot apply mapping annotations to both fields and properties in a single entity.
Persistent Fields
If the entity class uses persistent fields, the Persistence runtime accesses entity class instance variables directly. All fields not annotated
javax.persistence.Transient
or not marked as Javatransient
will be persisted to the data store. The object/relational mapping annotations must be applied to the instance variables.Persistent Properties
If the entity uses persistent properties, the entity must follow the method conventions of JavaBeans components. JavaBeans-style properties use getter and setter methods that are typically named after the entity class's instance variable names. For every persistent property
property
of typeType
of the entity, there is a getter methodget
Property
and setter methodset
Property
. If the property is a boolean, you may useis
Property
instead ofget
Property
. For example, if aCustomer
entity uses persistent properties, and has a private instance variable calledfirstName
, the class defines agetFirstName
andsetFirstName
method for retrieving and setting the state of thefirstName
instance variable.The method signature for single-valued persistent properties are as follows:
Collection-valued persistent fields and properties must use the supported Java collection interfaces regardless of whether the entity uses persistent fields or properties. The following collection interfaces may be used:
If the entity class uses persistent fields, the type in the above method signatures must be one of these collection types. Generic variants of these collection types may also be used. For example, if the
Customer
entity has a persistent property that contains a set of phone numbers, it would have the following methods:The object/relational mapping annotations for must be applied to the getter methods. Mapping annotations cannot be applied to fields or properties annotated
@Transient
or markedtransient
.Primary Keys in Entities
Each entity has a unique object identifier. A customer entity, for example, might be identified by a customer number. The unique identifier, or primary key, enables clients to locate a particular entity instance. Every entity must have a primary key. An entity may have either a simple or a composite primary key.
Simple primary keys use the
javax.persistence.Id
annotation to denote the primary key property or field.Composite primary keys must correspond to either a single persistent property or field, or to a set of single persistent properties or fields. Composite primary keys must be defined in a primary key class. Composite primary keys are denoted using the
javax.persistence.EmbeddedId
andjavax.persistence.IdClass
annotations.The primary key, or the property or field of a composite primary key, must be one of the following Java language types:
Floating point types should never be used in primary keys. If you use a generated primary key, only integral types will be portable.
Primary Key Classes
A primary key class must meet these requirements:
- The access control modifier of the class must be
public
.- The properties of the primary key class must be
public
orprotected
if property-based access is used.- The class must have a public default constructor.
- The class must implement the
hashCode()
andequals(Object other)
methods.- The class must be serializable.
- A composite primary key must be represented and mapped to multiple fields or properties of the entity class, or must be represented and mapped as an embeddable class.
- If the class is mapped to multiple fields or properties of the entity class, the names and types of the primary key fields or properties in the primary key class must match those of the entity class.
The following primary key class is a composite key, the
orderId
anditemId
fields together uniquely identify an entity.public final class LineItemKey implements Serializable { public Integer orderId; public int itemId; public LineItemKey() {} public LineItemKey(Integer orderId, int itemId) { this.orderId = orderId; this.itemId = itemId; } public boolean equals(Object otherOb) { if (this == otherOb) { return true; } if (!(otherOb instanceof LineItemKey)) { return false; } LineItemKey other = (LineItemKey) otherOb; return ( (orderId==null?other.orderId==null:orderId.equals (other.orderId) ) && (itemId == other.itemId) ); } public int hashCode() { return ( (orderId==null?0:orderId.hashCode()) ^ ((int) itemId) ); } public String toString() { return "" + orderId + "-" + itemId; } }Multiplicity in Entity Relationships
There are four types of multiplicities: one-to-one, one-to-many, many-to-one, and many-to-many.
One-to-one: Each entity instance is related to a single instance of another entity. For example, to model a physical warehouse in which each storage bin contains a single widget,
StorageBin
andWidget
would have a one-to-one relationship. One-to-one relationships use thejavax.persistence.OneToOne
annotation on the corresponding persistent property or field.One-to-many: An entity instance can be related to multiple instances of the other entities. A sales order, for example, can have multiple line items. In the order application,
Order
would have a one-to-many relationship withLineItem
. One-to-many relationships use thejavax.persistence.OneToMany
annotation on the corresponding persistent property or field.Many-to-one: Multiple instances of an entity can be related to a single instance of the other entity. This multiplicity is the opposite of a one-to-many relationship. In the example just mentioned, from the perspective of
LineItem
the relationship toOrder
is many-to-one. Many-to-one relationships use thejavax.persistence.ManyToOne
annotation on the corresponding persistent property or field.Many-to-many: The entity instances can be related to multiple instances of each other. For example, in college each course has many students, and every student may take several courses. Therefore, in an enrollment application,
Course
andStudent
would have a many-to-many relationship. Many-to-many relationships use thejavax.persistence.ManyToMany
annotation on the corresponding persistent property or field.Direction in Entity Relationships
The direction of a relationship can be either bidirectional or unidirectional. A bidirectional relationship has both an owning side and an inverse side. A unidirectional relationship has only an owning side. The owning side of a relationship determines how the Persistence runtime makes updates to the relationship in the database.
Bidirectional Relationships
In a bidirectional relationship, each entity has a relationship field or property that refers to the other entity. Through the relationship field or property, an entity class's code can access its related object. If an entity has a related field, then we often say that it "knows" about its related object. For example, if
Order
knows whatLineItem
instances it has and ifLineItem
knows whatOrder
it belongs to, then they have a bidirectional relationship.Bidirectional relationships must follow these rules:
- The inverse side of a bidirectional relationship must refer to its owning side by using the
mappedBy
element of the@OneToOne
,@OneToMany
, or@ManyToMany
annotation. ThemappedBy
element designates the property or field in the entity that is the owner of the relationship.- The many side of many-to-one bidirectional relationships must not define the
mappedBy
element. The many side is always the owning side of the relationship.- For one-to-one bidirectional relationships, the owning side corresponds to the side that contains the corresponding foreign key.
- For many-to-many bidirectional relationships either side may be the owning side.
Unidirectional Relationships
In a unidirectional relationship, only one entity has a relationship field or property that refers to the other. For example,
LineItem
would have a relationship field that identifiesProduct
, butProduct
would not have a relationship field or property forLineItem
. In other words,LineItem
knows aboutProduct
, butProduct
doesn't know whichLineItem
instances refer to it.Queries and Relationship Direction
Java Persistence query language queries often navigate across relationships. The direction of a relationship determines whether a query can navigate from one entity to another. For example, a query can navigate from
LineItem
toProduct
but cannot navigate in the opposite direction. ForOrder
andLineItem
, a query could navigate in both directions, because these two entities have a bidirectional relationship.Cascade Deletes and Relationships
Entities that use relationships often have dependencies on the existence of the other entity in the relationship. For example, a line item is part of an order, and if the order is deleted, then the line item should also be deleted. This is called a cascade delete relationship.
Cascade delete relationships are specified using the
cascade=REMOVE
element specification for@OneToOne
and@OneToMany
relationships. For example:Entity Inheritance
Entities support class inheritance, polymorphic associations, and polymorphic queries. They can extend non-entity classes, and non-entity classes can extend entity classes. Entity classes can be both abstract and concrete.
The
roster
example application demonstrates entity inheritance, and is described in Entity Inheritance in the roster Application.Abstract Entities
An abstract class may be declared an entity by decorating the class with
@Entity
. Abstract entities differ from concrete entities only in that they cannot be instantiated.Abstract entities can be queried just like concrete queries. If an abstract entity is the target of a query, the query operates on all the concrete subclasses of the abstract entity.
@Entity public abstract class Employee { @Id protected Integer employeeId; ... } @Entity public class FullTimeEmployee extends Employee { protected Integer salary; ... } @Entity public class PartTimeEmployee extends Employee { protected Float hourlyWage; }Mapped Superclasses
Entities may inherit from superclasses that contain persistent state and mapping information, but are not entities. That is, the superclass is not decorated with the
@Entity
annotation, and is not mapped as an entity by the Java Persistence provider. These superclasses are most often used when you have state and mapping information common to multiple entity classes.Mapped superclasses are specified by decorating the class with the
javax.persistence.MappedSuperclass
annotation.@MappedSuperclass public class Employee { @Id protected Integer employeeId; ... } @Entity public class FullTimeEmployee extends Employee { protected Integer salary; ... } @Entity public class PartTimeEmployee extends Employee { protected Float hourlyWage; ... }Mapped superclasses are not queryable, and can't be used in
EntityManager
orQuery
operations. You must use entity subclasses of the mapped superclass inEntityManager
orQuery
operations. Mapped superclasses can't be targets of entity relationships. Mapped superclasses can be abstract or concrete.Mapped superclasses do not have any corresponding tables in the underlying datastore. Entities that inherit from the mapped superclass define the table mappings. For instance, in the code sample above the underlying tables would be
FULLTIMEEMPLOYEE
andPARTTIMEEMPLOYEE
, but there is noEMPLOYEE
table.Non-Entity Superclasses
Entities may have non-entity superclasses, and these superclasses can be either abstract or concrete. The state of non-entity superclasses is non-persistent, and any state inherited from the non-entity superclass by an entity class is non-persistent. Non-entity superclasses may not be used in
EntityManager
orQuery
operations. Any mapping or relationship annotations in non-entity superclasses are ignored.Entity Inheritance Mapping Strategies
You can configure how the Java Persistence provider maps inherited entities to the underlying datastore by decorating the root class of the hierarchy with the
javax.persistence.Inheritance
annotation. There are three mapping strategies that are used to map the entity data to the underlying database:The strategy is configured by setting the
strategy
element of@Inheritance
to one of the options defined in thejavax.persistence.InheritanceType
enumerated type:The default strategy is
InheritanceType.SINGLE_TABLE
, and is used if the@Inheritance
annotation is not specified on the root class of the entity hierarchy.The Single Table per Class Hierarchy Strategy
With this strategy, which corresponds to the default
InheritanceType.SINGLE_TABLE
, all classes in the hierarchy are mapped to a single table in the database. This table has a discriminator column, a column that contains a value that identifies the subclass to which the instance represented by the row belongs.The discriminator column can be specified by using the
javax.persistence.DiscriminatorColumn
annotation on the root of the entity class hierarchy.
The
javax.persistence.DiscriminatorType
enumerated type is used to set the type of the discriminator column in the database by setting thediscriminatorType
element of@DiscriminatorColumn
to one of the defined types.DiscriminatorType
is defined as:If
@DiscriminatorColumn
is not specified on the root of the entity hierarchy and a discriminator column is required, the Persistence provider assumes a default column name ofDTYPE
, and column type ofDiscriminatorType.STRING
.The
javax.persistence.DiscriminatorValue
annotation may be used to set the value entered into the discriminator column for each entity in a class hierarchy. You may only decorate concrete entity classes with@DiscriminatorValue
.If
@DiscriminatorValue
is not specified on an entity in a class hierarchy that uses a discriminator column, the Persistence provider will provide a default, implemenation-specific value. If thediscriminatorType
element of@DiscriminatorColumn
isDiscriminatorType.STRING
, the default value is the name of the entity.This strategy provides good support for polymorphic relationships between entities and queries that cover the entire entity class hierarchy. However, it requires the columns that contain the state of subclasses to be nullable.
The Table per Concrete Class Strategy
In this strategy, which corresponds to
InheritanceType.TABLE_PER_CLASS
, each concrete class is mapped to a separate table in the database. All fields or properties in the class, including inherited fields or properties, are mapped to columns in the class's table in the database.This strategy provides poor support for polymorphic relationships, and usually requires either SQL
UNION
queries or separate SQL queries for each subclass for queries that cover the entire entity class hierarchy.Support for this strategy is optional, and may not be supported by all Java Persistence API providers. The default Java Persistence API provider in the Application Server does not support this strategy.
The Joined Subclass Strategy
In this strategy, which corresponds to
InheritanceType.JOINED
, the root of the class hierarchy is represented by a single table, and each subclass has a separate table that only contains those fields specific to that subclass. That is, the subclass table does not contain columns for inherited fields or properties. The subclass table also has a column or columns that represent its primary key, which is a foreign key to the primary key of the superclass table.This strategy provides good support for polymorphic relationships, but requires one or more join operations to be performed when instantiating entity subclasses. This may result in poor performance for extensive class hierarchies. Similarly, queries that cover the entire class hierarchy require join operations between the subclass tables, resulting in decreased performance.
Some Java Persistence API providers, including the default provider in the Application Server, require a discriminator column in the table that corresponds to the root entity when using the joined subclass strategy. If you are not using automatic table creation in your application, make sure the database table is set up correctly for the discriminator column defaults, or use the
@DiscriminatorColumn
annotation to match your database schema. For information on discriminator columns, see The Single Table per Class Hierarchy Strategy.