![]() | |
|
A method may be designated as a lifecycle callback method to receive notification of entity lifecycle events.
A lifecycle callback method may be defined on an entity class, a mapped superclass, or an entity listener class associated with an entity or mapped superclass. An entity listener class is a class whose methods are invoked in response to lifecycle events on an entity. ANY NUMBER of entity listener classes may be defined for an entity class or mapped superclass.
Default entity listeners - entity listeners that apply to all entities in the persistence unit - can be specified by means of the XML descriptor.
Lifecycle callback methods and entity listener classes are defined by means of metadata annotations or the XML descriptor. When annotations are used, one or more entity listener classes are denoted using the EntityListeners annotation on the entity class or mapped superclass. If multiple entity listeners are defined, the order in which they are invoked is determined by the order in which they are specified in the EntityListeners annotation. The XML descriptor may be used as an alternative to specify the invocation order of entity listeners or to override the order specified in metadata annotations.
Any subset or combination of annotations may be specified on an entity class, mapped superclass, or listener class. A single class MAY NOT have more than ONE lifecycle callback method for the same lifecycle event. The same method may be used for multiple callback events.
Multiple entity classes and mapped superclasses in an inheritance hierarchy may define listener classes and/or lifecycle callback methods directly on the class.
The entity listener class must have a public no-arg constructor.
Entity listeners are stateless. The lifecycle of an entity listener is unspecified.
The following rules apply to lifecycle callbacks:
Lifecycle callback methods may throw unchecked/runtime exceptions. A runtime exception thrown by a callback method that executes within a transaction causes that transaction to be rolled back.
Lifecycle callbacks can invoke JNDI, JDBC, JMS, and enterprise beans.
In general, portable applications should not invoke EntityManager or Query operations, access other entity instances, or modify relationships in a lifecycle callback method.
When invoked from within a Java EE environment, the callback listeners for an entity share the enterprise naming context of the invoking component, and the entity callback methods are invoked in the transaction and security contexts of the calling component at the time at which the callback method is invoked.
Lifecycle Callback Methods
Entity lifecycle callback methods can be defined on an entity listener class and/or directly on an entity class or mapped superclass.
Lifecycle callback methods are annotated with annotations designating the callback events for which they are invoked or are mapped to the callback event using the XML descriptor.
The annotations used for callback methods on the entity class or mapped superclass and for callback methods on the entity listener class are the same. The signatures of individual methods, however, differ.
Callback methods defined on an entity class or mapped superclass have the following signature:
void <METHOD>()
When declaring callback methods on a persistent class, any method may be used which takes no arguments and is not shared with any property access fields. Multiple events can be assigned to a single method as well.
Below is an example of how to declare callback methods on persistent classes:
/** * Example persistent class declaring entity listener. */ @Entity public class Magazine { @Transient private byte[][] data; @ManyToMany private List<Photo> photos; @PostLoad public void convertPhotos() { data = new byte[photos.size()][]; for (int i = 0; i < photos.size(); i++) { data[i] = photos.get(i).toByteArray(); } } @PreDelete public void logMagazineDeletion() { getLog().debug("deleting magazine containing" + photos.size() + " photos."); } }
In an XML mapping file, we can define the same methods without annotations:
<entity class="Magazine"> <pre-remove>logMagazineDeletion</pre-remove> <post-load>convertPhotos</post-load> </entity>
Callback methods defined on an entity listener class have the following signature:
void <METHOD>(Object)
The Object argument is the entity instance for which the callback method is invoked. It may be declared as the actual entity type.
Mixing lifecycle event code into your persistent classes is not always ideal. It is often more elegant to handle cross-cutting lifecycle events in a non-persistent listener class. JPA allows for this, requiring only that listener classes have a public no-arg constructor. Like persistent classes, your listener classes can consume any number of callbacks. The callback methods must take in a single java.lang.Object argument which represents the persistent object that triggered the event.
Entities can enumerate listeners using the EntityListeners annotation. This annotation takes an array of listener classes as its value.
Below is an example of how to declare an entity and its corresponding listener classes:
/** * Example persistent class declaring entity listener. */ @Entity @EntityListeners({ MagazineLogger.class, ... }) public class Magazine { ... }
/** * Example entity listener. */ public class MagazineLogger { @PostPersist public void logAddition(Object pc) { getLog ().debug ("Added new magazine:" + ((Magazine) pc).getTitle ()); } @PreRemove public void logDeletion(Object pc) { getLog().debug("Removing from circulation:" + ((Magazine) pc).getTitle()); } }
In XML, we define both the listeners and their callback methods as so:
<entity class="Magazine"> <entity-listeners> <entity-listener class="MagazineLogger"> <post-persist>logAddition</post-persist> <pre-remove>logDeletion</pre-remove> </entity-listener> </entity-listeners> </entity>
The callback methods can have public, private, protected, or package level access, but MUST NOT be static or final.
The following annotations are defined to designate lifecycle event callback methods of the corresponding types:
@PrePersist: Methods marked with this annotation will be invoked BEFORE an object is persisted. This could be used for assigning primary key values to persistent objects. This is equivalent to the XML element tag pre-persist.
@PostPersist: Methods marked with this annotation will be invoked AFTER an object has transitioned to the persistent state. You might want to use such methods to update a screen after a new row is added. This is equivalent to the XML element tag post-persist.
@PreRemove: Methods marked with this annotation will be invoked BEFORE an object transactions to the DELETED state. Access to persistent fields is valid within this method. You might use this method to cascade the deletion to related objects based on complex criteria, or to perform other cleanup. This is equivalent to the XML element tag pre-remove.
@PostRemove: Methods marked with this annotation will be invoked AFTER an object has been marked as to be deleted. This is equivalent to the XML element tag post-remove.
@PreUpdate: Methods marked with this annotation will be invoked just the persistent values in your objects are flushed to the datastore. This is equivalent to the XML element tag pre-update.
@PreUpdate is the complement to @PostLoad. While methods marked with @PostLoad are most often used to initialize non-persistent values from persistent data, methods annotated with @PreUpdate is normally used to set persistent fields with information cached in non-persistent data.
@PostUpdate: Methods marked with this annotation will be invoked AFTER changes to a given instance have been stored to the datastore. This is useful for clearing stale data cached at the application layer. This is equivalent to the XML element tag post-update.
@PostLoad: Methods marked with this annotation will be invoked after all eagerly fetched fields of your class have been loaded from the datastore. No other persistent fields can be accessed in this method. This is equivalent to the XML element tag post-load.
@PostLoad is often used to initialize non-persistent fields whose values depend on the values of persistent fields, such as a complex datastructure.
Semantics of the Life Cycle Callback Methods for Entities
The @PrePersist and @PreRemove callback methods are invoked for a given entity BEFORE the respective EntityManager persist and remove operations for that entity are executed. For entities to which the merge operation has been applied and causes the creation of newly managed instances, the @PrePersist callback methods will be invoked for the managed instance AFTER the entity state has been copied to it. These @PrePersist and @PreRemove callbacks will also be invoked on all entities to which these operations are cascaded. The @PrePersist and @PreRemove methods will always be invoked as part of the synchronous persist, merge, and remove operations.
The @PostPersist and @PostRemove callback methods are invoked for an entity AFTER the entity has been made persistent or removed. These callbacks will also be invoked on all entities to which these operations are cascaded. The @PostPersist and @PostRemove methods will be invoked AFTER the database INSERT and DELETE operations respectively. These database operations may occur directly after the persist, merge, or remove operations have been invoked or they may occur directly after a flush operation has occurred (which may be at the end of the transaction). Generated primary key values are available in the @PostPersist method.
The @PreUpdate and @PostUpdate callbacks occur BEFORE and AFTER the database UPDATE operations to entity data respectively. These database operations may occur at the time the entity state is updated or they may occur at the time state is flushed to the database (which may be at the end of the transaction).
The @PostLoad method for an entity is invoked AFTER the entity has been loaded into the current persistence context from the database or after the refresh operation has been applied to it. The @PostLoad method is invoked before a query result is returned or accessed or before an association is traversed.
Multiple Lifecycle Callback Methods for an Entity Lifecycle Event
If multiple callback methods are defined for an entity lifecycle event, the ordering of the invocation of these methods is as follows.
Default listeners, if any, are invoked first, in the order specified in the XML descriptor. Default listeners apply to all entities in the persistence unit, unless explicitly excluded by means of the ExcludeDefaultListeners annotation or exclude-default-listeners XML element.
The lifecycle callback methods defined on the entity listener classes for an entity class or mapped superclass are invoked in the same order as the specification of the entity listener classes in the EntityListeners annotation.
If MULTIPLE classes in an inheritance hierarchy - entity classes and/or mapped superclasses - define entity listeners, the listeners defined for a SUPERCLASS are invoked BEFORE the listeners defined for its subclasses in this order. The ExcludeSuperclassListeners annotation or exclude-superclass-listeners XML element may be applied to an entity class or mapped superclass to exclude the invocation of the listeners defined by the entity listener classes for the superclasses of the entity or mapped superclass. The excluded listeners are excluded from the class to which the ExcludeSuperclassListeners annotation or element has been specified and its subclasses. The ExcludeSuperclassListeners annotation (or exclude-superclass-listeners XML element) DOES NOT cause default entity listeners to be excluded from invocation.
If a lifecycle callback method for the same lifecycle event is also specified on the entity class and/or one or more of its entity or mapped superclasses, the callback methods on the entity class and/or superclasses are invoked AFTER the other lifecycle callback methods, most general superclass first. A class is permitted to override an inherited callback method of the same callback type, and in this case, the overridden method is NOT invoked.
Callback methods are invoked by the persistence provider runtime in the order specified. If the callback method execution terminates normally, the persistence provider runtime then invokes the next callback method, if any.
The XML descriptor may be used to OVERRIDE the lifecycle callback method invocation order specified in annotations.
Example:
@Entity public class Animal { .... @PostPersist protected void postPersistAnimal() { .... } }
@Entity @EntityListeners(PetListener.class) public class Pet extends Animal { ... }
@Entity @EntityListeners({CatListener.class, CatListener2.class}) public class Cat extends Pet { ... }
public class PetListener { @PostPersist protected void postPersistPetListenerMethod(Object pet) { ... } }
public class CatListener { @PostPersist protected void postPersistCatListenerMethod(Object cat) { ... } }
public class CatListener2 { @PostPersist protected void postPersistCatListener2Method(Object cat) { ... } }
CASE 1: If a @PostPersist event occurs on an instance of Cat, the following methods are called in order:
postPersistPetListenerMethod
postPersistCatListenerMethod
postPersistCatListener2Method
postPersistAnimal
Assume that SiameseCat is defined as a subclass of Cat:
@EntityListeners(SiameseCatListener.class) @Entity public class SiameseCat extends Cat { ... @PostPersist protected void postPersistSiameseCat() { ... } }
public class SiameseCatListener { @PostPersist protected void postPersistSiameseCatListenerMethod(Object cat) { ... } }
CASE 2: If a @PostPersist event occurs on an instance of SiameseCat, the following methods are called in order:
postPersistPetListenerMethod
postPersistCatListenerMethod
postPersistCatListener2Method
postPersistSiameseCatListenerMethod
postPersistAnimal
postPersistSiameseCat
Assume the definition of SiameseCat were instead:
@EntityListeners(SiameseCatListener.class) @Entity public class SiameseCat extends Cat { ... @PostPersist protected void postPersistAnimal() { ... } }
CASE 3: In this case, the following methods would be called in order, where postPersistAnimal is the @PostPersist method defined in the SiameseCat class:
postPersistPetListenerMethod
postPersistCatListenerMethod
postPersistCatListener2Method
postPersistSiameseCatListenerMethod
postPersistAnimal
Entity listener methods are invoked in a specific order when a given event is fired. So-called default listeners are invoked first: these are listeners which have been defined in a package annotation or in the root element of XML mapping files. Next, entity listeners are invoked in the order of the inheritance hierarchy, with superclass listeners being invoked before subclass listeners. Finally, if an entity has multiple listeners for the same event, the listeners are invoked in declaration order.
You can exclude default listeners and listeners defined in superclasses from the invocation chain through the use of two class-level annotations:
ExcludeDefaultListeners: This annotation indicates that no default listeners will be invoked for this class, or any of its subclasses. The XML equivalent is the empty exclude-default-listeners element.
ExcludeSuperclassListeners: This annotation will cause JPA to skip invoking any listeners declared in superclasses. The XML equivalent is empty the exclude-superclass-listeners element.
![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |