Storing JPA Entity Objects
New entity objects can be stored in the database either explicitly by invoking the persist
EntityManager.persist(entity) - JPA MethodMake an instance managed and persistent. method or implicitly as a result of a cascade operation.
This page covers the following topics:
Explicit Persist
The following code stores an instance of the Employee
entity class in the database:
Employee employee = new Employee("Samuel", "Joseph", "Wurzelbacher"); em.getTransactionEntityManager.getTransaction() - JPA MethodReturn the resource-levelEntityTransaction
object.().beginEntityTransaction.begin() - JPA MethodStart a resource transaction.(); em.persistEntityManager.persist(entity) - JPA MethodMake an instance managed and persistent.(employee); em.getTransactionEntityManager.getTransaction() - JPA MethodReturn the resource-levelEntityTransaction
object.().commitEntityTransaction.commit() - JPA MethodCommit the current resource transaction, writing any unflushed changes to the database.();
The Employee
instance is constructed as an ordinary Java object and its initial state is New. An explicit call to persist
EntityManager.persist(entity) - JPA MethodMake an instance managed and persistent. associates the object with an owner
and changes its state to Managed. The new entity object is stored in the database when the transaction is committed. EntityManager
javax.persistence.EntityManager - JPA InterfaceInterface used to interact with the persistence context. em
An IllegalArgumentException
is thrown by persist
EntityManager.persist(entity) - JPA MethodMake an instance managed and persistent. if the argument is not an instance of an entity class. Only instances of entity classes can be stored in the database independently. Objects of other persistable types can only be stored in the database embedded in containing entities (as field values).
A TransactionRequiredException
javax.persistence.TransactionRequiredException - JPA ExceptionThrown by the persistence provider when a transaction is required but is not active. is thrown if there is no active transaction when persist
is called because operations that modify the database require an active transaction.
If the database already contains another entity of the same type with the same primary key, an EntityExistsException
javax.persistence.EntityExistsException - JPA ExceptionThrown by the persistence provider when {@link EntityManager#persist(Object) EntityManager.persist(Object)} is called and the entity already exists. is thrown. The exception is thrown either by persist
EntityManager.persist(entity) - JPA MethodMake an instance managed and persistent. (if that existing entity object is currently managed by the EntityManager
) or by commit
EntityTransaction.commit() - JPA MethodCommit the current resource transaction, writing any unflushed changes to the database..
Referenced Embedded Objects
The following code stores an Employee
instance with a reference to an Address
instance:
Employee employee = new Employee("Samuel", "Joseph", "Wurzelbacher"); Address address = new Address("Holland", "Ohio"); employee.setAddress(address); em.getTransactionEntityManager.getTransaction() - JPA MethodReturn the resource-levelEntityTransaction
object.().beginEntityTransaction.begin() - JPA MethodStart a resource transaction.(); em.persistEntityManager.persist(entity) - JPA MethodMake an instance managed and persistent.(employee); em.getTransactionEntityManager.getTransaction() - JPA MethodReturn the resource-levelEntityTransaction
object.().commitEntityTransaction.commit() - JPA MethodCommit the current resource transaction, writing any unflushed changes to the database.();
Instances of persistable types other than entity classes are automatically stored embedded in containing entity objects. Therefore, if Address
is defined as an embeddable class the Employee
entity object is automatically stored in the database with its Address
instance as an embedded object.
Notice that embedded objects cannot be shared by multiple entity objects. Each containing entity object should have its own embedded objects.
Referenced Entity Objects
On the other hand, suppose that the Address
class in the code above is defined as an entity class. In this case, the referenced Address
instance is not stored in the database automatically with the referencing Employee
instance.
To avoid a dangling reference in the database, an IllegalStateException
is thrown on commit if a persisted entity object has to be stored in the database in a transaction and it references another entity object that is not expected to be stored in the database at the end of that transaction.
It is the application's responsibility to verify that when an object is stored in the database, the entire closure of entity objects that are reachable from that object by navigation through persistent reference fields is also stored in the database. This can be done either by explicit persist of every reachable object or alternatively by setting automatic cascading persist.
Cascading Persist
Marking a reference field with CascadeTypejavax.persistence.CascadeType - JPA EnumDefines the set of cascadable operations that are propagated
to the associated entity..
PERSISTjavax.persistence.CascadeType.PERSIST - JPA Enum ConstantCascade persist operation
(or CascadeTypejavax.persistence.CascadeType - JPA EnumDefines the set of cascadable operations that are propagated
to the associated entity..ALLjavax.persistence.CascadeType.ALL - JPA Enum ConstantCascade all operations
that also covers PERSISTjavax.persistence.CascadeType.PERSIST - JPA Enum ConstantCascade persist operation
) indicates that persistEntityManager.persist(entity) - JPA MethodMake an instance managed and persistent. operations should be cascaded automatically to entity objects that are referenced by that field (multiple entity objects can be referenced by a collection field):
@Entityjavax.persistence.Entity - JPA AnnotationSpecifies that the class is an entity.
class Employee {
:
@OneToOnejavax.persistence.OneToOne - JPA AnnotationSpecifies a single-valued association to another entity that has
one-to-one multiplicity.(cascadejavax.persistence.OneToOne.cascade - JPA Annotation Attribute(Optional) The operations that must be cascaded to
the target of the association.=CascadeTypejavax.persistence.CascadeType - JPA EnumDefines the set of cascadable operations that are propagated
to the associated entity..PERSISTjavax.persistence.CascadeType.PERSIST - JPA Enum ConstantCascade persist operation
)
private Address address;
:
}
In the example above, the Employee
entity class contains an address
field that references an instance of Address
, which is another entity class. Due to the CascadeType.PERSIST
setting, when an Employee
instance is persisted the operation is automatically cascaded to the referenced Address
instance which is then automatically persisted without the need for a separate persist
call for Address
. Cascading may continue recursively when applicable (e.g. to entity objects that the Address
object references, etc.).
Global Cascading Persist
Instead of specifying CascadeTypejavax.persistence.CascadeType - JPA EnumDefines the set of cascadable operations that are propagated
to the associated entity..PERSISTjavax.persistence.CascadeType.PERSIST - JPA Enum ConstantCascade persist operation
individually for every relevant reference field, it can be specified globally for any persistent reference, either by setting the ObjectDB configuration or in a JPA portable way, by specifying the cascade-persist
XML element in the XML mapping file:
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" version="1.0"> <persistence-unit-metadata> <persistence-unit-defaults> <cascade-persist/> </persistence-unit-defaults> </persistence-unit-metadata> </entity-mappings>
The mapping file has to be located either in the default location, META-INF/orm.xml
, or in another location that is specified explicitly in the persistence unit definition (in persistence.xml
).
Batch Store
Storing a large number of entity objects requires special consideration. The combination of the clear
and flush
methods can be used to save memory in large transactions:
em.getTransactionEntityManager.getTransaction() - JPA MethodReturn the resource-levelEntityTransaction
object.().beginEntityTransaction.begin() - JPA MethodStart a resource transaction.(); for (int i = 1; i <= 1000000; i++) { Point point = new Point(i, i); em.persistEntityManager.persist(entity) - JPA MethodMake an instance managed and persistent.(point); if ((i % 10000) == 0) { em.flushEntityManager.flush() - JPA MethodSynchronize the persistence context to the underlying database.(); em.clearEntityManager.clear() - JPA MethodClear the persistence context, causing all managed entities to become detached.(); } } em.getTransactionEntityManager.getTransaction() - JPA MethodReturn the resource-levelEntityTransaction
object.().commitEntityTransaction.commit() - JPA MethodCommit the current resource transaction, writing any unflushed changes to the database.();
Managed entity objects consume more memory than ordinary non managed Java objects. Therefore, holding 1,000,000 managed Point
instances in the persistence context might consume too much memory. The sample code above clears the persistence context after every 10,000 persists. Updates are flushed to the database before clearing, otherwise they would be lost.
Updates that are sent to the database using
are considered temporary and are only visible to the owner flush
EntityManager.flush() - JPA MethodSynchronize the persistence context to the
underlying database.EntityManager
javax.persistence.EntityManager - JPA InterfaceInterface used to interact with the persistence context. until a commit. With no explicit commit
EntityTransaction.commit() - JPA MethodCommit the current resource transaction, writing any unflushed changes to the database., these updates are later discarded. The combination of clear
EntityManager.clear() - JPA MethodClear the persistence context, causing all managed entities to become detached. and flush
EntityManager.flush() - JPA MethodSynchronize the persistence context to the underlying database. enables moving the temporary updates from memory to the database.
Note: Flushing updates to the database is sometimes also useful before executing queries in order to get up to date results.
Storing a large amount of entity objects can also be performed by multiple transactions:
em.getTransactionEntityManager.getTransaction() - JPA MethodReturn the resource-levelEntityTransaction
object.().beginEntityTransaction.begin() - JPA MethodStart a resource transaction.(); for (int i = 1; i <= 1000000; i++) { Point point = new Point(i, i); em.persistEntityManager.persist(entity) - JPA MethodMake an instance managed and persistent.(point); if ((i % 10000) == 0) { em.getTransactionEntityManager.getTransaction() - JPA MethodReturn the resource-levelEntityTransaction
object.().commitEntityTransaction.commit() - JPA MethodCommit the current resource transaction, writing any unflushed changes to the database.(); em.clearEntityManager.clear() - JPA MethodClear the persistence context, causing all managed entities to become detached.(); em.getTransactionEntityManager.getTransaction() - JPA MethodReturn the resource-levelEntityTransaction
object.().beginEntityTransaction.begin() - JPA MethodStart a resource transaction.(); } } em.getTransactionEntityManager.getTransaction() - JPA MethodReturn the resource-levelEntityTransaction
object.().commitEntityTransaction.commit() - JPA MethodCommit the current resource transaction, writing any unflushed changes to the database.();
Splitting a batch store into multiple transactions is more efficient than using one transaction with multiple invocations of the flush
and clear
methods. So using multiple transactions is preferred when applicable.