Calling remove on an object will also cascade the remove operation across any relationship that is marked as cascade remove.
Note that cascade remove only effects the remove call. If you have a relationship that is cascade remove, and remove an object from the collection, or dereference an object, it will not be removed. You must explicitly call remove on the object to have it deleted. Some JPA providers
provide an extension to provide this behavior, and in JPA 2.0 there will be an orphanRemoval option on OneToMany and OneToOne mappings to provide this.
[edit] Reincarnation
Normally an object that has been removed, stays removed, but in some cases you may need to bring the object back to life. This normally occurs with natural ids, not generated ones, where a new object would always get an new id. Generally the desire to reincarnate an object occurs from a bad object model design, normally the desire to change the class type of an object (which cannot be done in Java, so a new object must be created). Normally the best solution is to change your object model to have your object hold a type object which defines its type, instead of using inheritance. But sometimes reincarnation is desirable.
When done it two separate transactions, this is normally fine, first you remove the object, then you persist it back. This can be more complex if you wish to remove and persist an object with the same Id in the same transaction. If you call remove on an object, then call persist on the same object, it will simply no longer be removed. If you call remove on an object, then call persist on a different object with the same Id the behavior may depend on your JPA provider, and probably will not work. If you call flush after calling remove, then call persist, then the object should be successfully reincarnated. Note that it will be a different row, the existing row will have been deleted, and a new row inserted. If you wish the same row to be updated, you may need to resort to using a native SQL update query.
[edit] Advanced
[edit] Refresh
The EntityManager.refresh() operation is used to refresh an object's state from the database.
This will revert any non-flushed changes made in the current transaction to the object, and refresh its state to what is currently defined on the database. If a flush has occurred, it will refresh to what was flushed. Refresh must be called on a managed object, so you may first need to find the object with the active EntityManager if you have a non-managed instance.
Refresh will cascade to any relationships marked cascade refresh, although it may be done lazily depending on your fetch type, so you may need to access the relationship to trigger the refresh. refresh can only be called on Entity objects, not on Embeddable objects, or
collections, or non-persistent objects. Embeddable objects are automatically refreshed as part of their owning Entity.
Refresh can be used to revert changes, or if your JPA provider supports caching, it can be used to refresh stale cached data. Sometimes it is desirable to have a Query or find operation refresh the results. Unfortunately JPA 1.0 does not define how this can be done. Some JPA providers offer query hints to allow refreshing to be enabled on a query.
TopLink / EclipseLink : Define a query hint "eclipselink.refresh" to allow refreshing to be enabled on a query.
JPA 2.0 defines a set of standard query hints for refeshing, see JPA 2.0 Cache APIs.
[edit] Example refresh
EntityManager em = getEntityManager(); em.refresh(employee);
[edit] Lock
See, Read and Write Locking.
[edit] Get Reference
The EntityManager.getReference() operation is used to obtain a handle to an object without
requiring it to be loaded. It is similar to the find operation, but may return a proxy or unfetched object. JPA does not require that getReference avoid loading the object, so some JPA providers may not support it and just perform a normal find operation. The object returned by
getReference should appear to be a normal object, if you access any method or attribute other than its Id it will trigger itself to be refreshed from the database.
The intention of getReference is that it could be used on an insert or update operation as a stand-in for a related object, if you only have its Id and want to avoid loading the object. Note that getReference does not verify the existence of the object as find does. If the object does not exist and you try to use the unfetched object in an insert or update you may get a foreign key constraint violation, or if you access the object it may trigger an exception.
[edit] Example getReference
EntityManager em = getEntityManager();
Employee manager = em.getReference(managerId); Employee employee = new Employee();
...
em.persist(employee);
employee.setManager(manager); em.commit();
[edit] Flush
The EntityManager.flush() operation can be used the write all changes to the database before
the transaction is committed. By default JPA does not normally write changes to the database until the transaction is committed. This is normally desirable as it avoids database access, resources and locks until required. It also allows database writes to be ordered, and batched for optimal database access, and to maintain integrity constraints and avoid deadlocks. This means that when you call persist, merge, or remove the database DML INSERT, UPDATE, DELETE is not executed, until commit, or until a flush is triggered.
Flush has several usages:
• Flush changes before a query execution to enable the query to return new objects and changes made in the persistence unit.
• Insert persisted objects to ensure their Ids are assigned and accessible to the application if using IDENTITY sequencing.
• Write all changes to the database to allow error handling of any database errors (useful when using JTA or SessionBeans).
• To flush and clear a batch for batch processing in a single transaction.
• Avoid constraint errors, or reincarnate an object.
[edit] Example flush
public long createOrder(Order order) throws ACMEException { EntityManager em = getEntityManager();
em.persist(order); try {
em.flush();
} catch (PersistenceException exception) { throw new ACMEException(exception); }
return order.getId(); }
[edit] Clear
The EntityManager.clear() operation can be used to clear the persistence context. This will
clear all objects read, changed, persisted, or removed from the current EntityManager or transaction. Changes that have already been written to the database through flush, or any changes made to the database will not be cleared. Any object that was read or persisted through the EntityManager is detached, meaning any changes made to it will not be tracked, and it should no longer be used unless merged into the new persistence context.
clear can be used similar to a rollback to abandon changes and restart a persistence context. If a transaction commit fails, or a rollback is performed the persistence context will automatically be cleared.
clear is similar to closing the EntityManager and creating a new one, the main difference being that clear can be called while a transaction is in progress. clear can also be used to free the objects and memory consumed by the EntityManager. It is important to note that an EntityManager is responsible for tracking and managing all objects read within its persistence context. In an application managed EntityManager this includes every objects read since the EntityManager was created, including every transaction the EntityManager was used for. If a long lived EntityManager is used, this is an intrinsic memory leak, so calling clear or closing the EntityManager and creating a new one is an important application design consideration. For JTA managed EntityManagers the persistence context is automatically cleared across each JTA transaction boundary.
Clearing is also important on large batch jobs, even if they occur in a single transaction. The batch job can be slit into smaller batches within the same transaction and clear can be called in between each batch to avoid the persistence context from getting too big.
[edit] Example clear
public void processAllOpenOrders() { EntityManager em = getEntityManager();
List<Long> openOrderIds = em.createQuery("SELECT o.id from Order o where o.isOpen = true");
em.getTransaction().begin(); try {
for (int batch = 0; batch < openOrderIds.size(); batch += 100) { for (int index = 0; index < 100 && (batch + index) <
openOrderIds.size(); index++) {
Long id = openOrderIds.get(batch + index); Order order = em.find(Order.class, id); order.process(em);
}
em.flush(); em.clear(); }
em.getTransaction().commit(); } catch (RuntimeException error) { if (em.getTransaction().isActive()) { em.getTransaction().rollback(); } } }
[edit] Close
The EntityManager.close() operation is used to release an application managed
EntityManager's resources. JEE JTA managed EntityManagers cannot be closed, as they are managed by the JTA transaction and JEE server.
The life-cycle of an EntityManager can last either a transaction, request, or a users session. Typically the life-cycle is per request, and the EntityManager is closed at the end of the request. The objects obtained from an EntityManager become detached when the EntityManager is closed, and any LAZY relationships may no longer be accessible if they were not accessed before the EntityManager was closed. Some JPA providers allow LAZY relationships to be accessed after close.
[edit] Example close
public Order findOrder(long id) {
EntityManager em = factory.createEntityManager(); Order order = em.find(Order.class, id);
order.getOrderLines().size(); em.close();
return order; }