ObjectDB ObjectDB

Storing JPA Entity Objects

New entity objects can be stored in the database either explicitly by invoking the persistpersist(entity)EntityManager's methodMake an instance managed and persistent.See JavaDoc Reference Page... method or implicitly as a result of a cascade operation.

Explicit Persist

The following code stores an instance of the Employee entity class in the database:

  Employee employee = new Employee("Samuel", "Joseph", "Wurzelbacher");
  em.getTransactiongetTransaction()EntityManager's methodReturn the resource-level EntityTransaction object.See JavaDoc Reference Page...().beginbegin()EntityTransaction's methodStart a resource transaction.See JavaDoc Reference Page...();
  em.persistpersist(entity)EntityManager's methodMake an instance managed and persistent.See JavaDoc Reference Page...(employee);
  em.getTransactiongetTransaction()EntityManager's methodReturn the resource-level EntityTransaction object.See JavaDoc Reference Page...().commitcommit()EntityTransaction's methodCommit the current resource transaction, writing any 
 unflushed changes to the database.See JavaDoc Reference Page...();

The Employee instance is constructed as an ordinary Java object and its initial state is New. An explicit call to persistpersist(entity)EntityManager's methodMake an instance managed and persistent.See JavaDoc Reference Page... associates the object with an owner EntityManagerjavax.persistence.EntityManagerJPA interfaceInterface used to interact with the persistence context.See JavaDoc Reference Page... em and changes its state to Managed. The new entity object is stored in the database when the transaction is committed.

An IllegalArgumentException is thrown by persistpersist(entity)EntityManager's methodMake an instance managed and persistent.See JavaDoc Reference Page... 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 TransactionRequiredExceptionjavax.persistence.TransactionRequiredExceptionJPA exceptionThrown by the persistence provider when a transaction is required but is not active.See JavaDoc Reference Page... 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 EntityExistsExceptionjavax.persistence.EntityExistsExceptionJPA exceptionThrown by the persistence provider when EntityManager.persist(Object) is called and the entity already exists.See JavaDoc Reference Page... is thrown. The exception is thrown either by persistpersist(entity)EntityManager's methodMake an instance managed and persistent.See JavaDoc Reference Page... (if that existing entity object is currently managed by the EntityManager) or by commitcommit()EntityTransaction's methodCommit the current resource transaction, writing any unflushed changes to the database.See JavaDoc Reference Page....

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.getTransactiongetTransaction()EntityManager's methodReturn the resource-level EntityTransaction object.See JavaDoc Reference Page...().beginbegin()EntityTransaction's methodStart a resource transaction.See JavaDoc Reference Page...();
  em.persistpersist(entity)EntityManager's methodMake an instance managed and persistent.See JavaDoc Reference Page...(employee);
  em.getTransactiongetTransaction()EntityManager's methodReturn the resource-level EntityTransaction object.See JavaDoc Reference Page...().commitcommit()EntityTransaction's methodCommit the current resource transaction, writing any 
 unflushed changes to the database.See JavaDoc Reference Page...();

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.CascadeTypeJPA enumDefines the set of cascadable operations that are propagated to the associated entity.See JavaDoc Reference Page....PERSISTCascadeType.PERSISTenum constantCascade persist operationSee JavaDoc Reference Page... (or CascadeTypejavax.persistence.CascadeTypeJPA enumDefines the set of cascadable operations that are propagated to the associated entity.See JavaDoc Reference Page....ALLCascadeType.ALLenum constantCascade all operationsSee JavaDoc Reference Page... that also covers PERSISTCascadeType.PERSISTenum constantCascade persist operationSee JavaDoc Reference Page...) indicates that persistpersist(entity)EntityManager's methodMake an instance managed and persistent.See JavaDoc Reference Page... 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.EntityJPA annotationSpecifies that the class is an entity.See JavaDoc Reference Page...
class Employee {
     :
    @OneToOnejavax.persistence.OneToOneJPA annotationDefines a single-valued association to another entity that has
 one-to-one multiplicity.See JavaDoc Reference Page...(cascadeOneToOne.cascadeannotation element(Optional) The operations that must be cascaded to 
 the target of the association.See JavaDoc Reference Page...=CascadeTypejavax.persistence.CascadeTypeJPA enumDefines the set of cascadable operations that are propagated 
 to the associated entity.See JavaDoc Reference Page....PERSISTCascadeType.PERSISTenum constantCascade persist operationSee JavaDoc Reference Page...)
    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.CascadeTypeJPA enumDefines the set of cascadable operations that are propagated to the associated entity.See JavaDoc Reference Page....PERSISTCascadeType.PERSISTenum constantCascade persist operationSee JavaDoc Reference Page... 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.getTransactiongetTransaction()EntityManager's methodReturn the resource-level EntityTransaction object.See JavaDoc Reference Page...().beginbegin()EntityTransaction's methodStart a resource transaction.See JavaDoc Reference Page...();
  for (int i = 1; i <= 1000000; i++) {
      Point point = new Point(i, i);
      em.persistpersist(entity)EntityManager's methodMake an instance managed and persistent.See JavaDoc Reference Page...(point);
      if ((i % 10000) == 0) {
          em.flushflush()EntityManager's methodSynchronize the persistence context to the
 underlying database.See JavaDoc Reference Page...();
          em.clearclear()EntityManager's methodClear the persistence context, causing all managed
 entities to become detached.See JavaDoc Reference Page...();
      }
  }
  em.getTransactiongetTransaction()EntityManager's methodReturn the resource-level EntityTransaction object.See JavaDoc Reference Page...().commitcommit()EntityTransaction's methodCommit the current resource transaction, writing any 
 unflushed changes to the database.See JavaDoc Reference Page...();

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 flushflush()EntityManager's methodSynchronize the persistence context to the underlying database.See JavaDoc Reference Page... are considered temporary and are only visible to the owner EntityManagerjavax.persistence.EntityManagerJPA interfaceInterface used to interact with the persistence context.See JavaDoc Reference Page... until a commit. With no explicit commitcommit()EntityTransaction's methodCommit the current resource transaction, writing any unflushed changes to the database.See JavaDoc Reference Page..., these updates are later discarded. The combination of clearclear()EntityManager's methodClear the persistence context, causing all managed entities to become detached.See JavaDoc Reference Page... and flushflush()EntityManager's methodSynchronize the persistence context to the underlying database.See JavaDoc Reference Page... 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.getTransactiongetTransaction()EntityManager's methodReturn the resource-level EntityTransaction object.See JavaDoc Reference Page...().beginbegin()EntityTransaction's methodStart a resource transaction.See JavaDoc Reference Page...();
  for (int i = 1; i <= 1000000; i++) {
      Point point = new Point(i, i);
      em.persistpersist(entity)EntityManager's methodMake an instance managed and persistent.See JavaDoc Reference Page...(point);
      if ((i % 10000) == 0) {
          em.getTransactiongetTransaction()EntityManager's methodReturn the resource-level EntityTransaction object.See JavaDoc Reference Page...().commitcommit()EntityTransaction's methodCommit the current resource transaction, writing any 
 unflushed changes to the database.See JavaDoc Reference Page...();
          em.clearclear()EntityManager's methodClear the persistence context, causing all managed
 entities to become detached.See JavaDoc Reference Page...();          
          em.getTransactiongetTransaction()EntityManager's methodReturn the resource-level EntityTransaction object.See JavaDoc Reference Page...().beginbegin()EntityTransaction's methodStart a resource transaction.See JavaDoc Reference Page...();
      }
  }
  em.getTransactiongetTransaction()EntityManager's methodReturn the resource-level EntityTransaction object.See JavaDoc Reference Page...().commitcommit()EntityTransaction's methodCommit the current resource transaction, writing any 
 unflushed changes to the database.See JavaDoc Reference Page...();

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.