Cmobilecom JPA 2.0.1 Developer Guide

16. Entity Listeners

Entity listeners define callbacks that are invoked when an entity lifecycle event occurs. Entity lifecycle events:

Callback Methods

Event callback methods can be defined in listener classes, entities or mapped-superclasses. For example,
public class EmployeeListener {
    @PrePersist
    public void prePersist(Object entity) {
    }
}

@Entity
@EntityListeners({EmployeeListener.class})
public class Employee {
    @PrePersist
    public void prePersist() {
    }
}

Callback Invocation Order

For a managed class hierarchy, the order of listener callbacks called for a lifecycle event:
  1. Default listeners
  2. Superclass entity or mapped-superclass listeners
  3. Entity listeners
  4. Superclass entity or mapped-superclass callback methods except overridden methods
  5. Entity callback method
For example,

Default listeners (defined in an ORM xml):

<entity-mappings>
    <persistence-unit-metadata>
        <persistence-unit-defaults>
            <entity-listeners>
                <entity-listener class="com.cmobilecom.jpa.example.managed_classes.DefaultListener"/>
            </entity-listeners>
        </persistence-unit-defaults>
    </persistence-unit-metadata>
</entity-mappings>
Default listener:
public class DefaultListener {
    
    @PrePersist
    public void prePersist(Object entity) {
    
    }

}
Managed class(entity and mapped-superclass) hierarchy:
                    Person
                      |
                   Employee
                    /     \
       FullTimeEmployee  PartTimeEmployee
    
@MappedSuperclass
@EntityListeners(PersonListener.class)
abstract public class Person {
    @PrePersist
    public void verifyBirthday() {
    
    }
}

@Entity
@EntityListeners({EmployeeListener.class, EmployeeListener2.class})
@ExcludeDefaultListeners
abstract public class Employee extends EducatedPerson {
    @PreRemove
    private void preRemove() {
    
    }
}

@Entity
@ExcludeSuperclassListeners
@EntityListeners(FullTimeEmployeeListener.class)
public class FullTimeEmployee extends Employee {
    @Override
    @PrePersist
    public void verifyBirthday() {
    
    }
}

@Entity
public class PartTimeEmployee extends Employee {
    @PrePersist
    public void verifyHourlyWage() {

    }
}
Listener example:
public class PersonListener {
    
    @PrePersist
    public void prePersist(Person person) {
    
    }
    
    @PostPersist
    void postPersist(Person person) {

    }
    
    @PreUpdate
    protected void preUpdate(Person person) {

    }
    
    @PostUpdate
    private void postUpdate(Person person) {

    }
    
    @PreRemove
    private void preRemove(Person person) {

    }
    
    @PostRemove
    private void postRemove(Person person) {

    }
    
    @PostLoad
    private void postLoad(Person person) {

    }
}
When EntityManager calls persist(aFullTimeEmployee), the callback methods for prePersist event are called in the following order:
  1. DefaultListener.prePersist() is not invoked since @ExcludeDefaultListeners is annotated on its superclass entity Employee.
  2. Superclass listeners(PersonListener, EmployeeListener, EmployeeListener2) are not invoked since @ExcludeSuperclassListeners is annotated on FullTimeEmployee entity.
  3. FullTimeEmployeeListener is called.
  4. FullTimeEmployee.verifyBirthday() is called, which override the inherited method
When EntityManager calls persist(aPartTimeEmployee), the callback methods for prePersist event are called in the following order:
  1. DefaultListener.prePersist() is not invoked since @ExcludeDefaultListeners is annotated on its superclass entity Employee.
  2. Superclass listeners(PersonListener, EmployeeListener, EmployeeListener2) are invoked in the listed order.
  3. Person.verifyBirthday() is called.
  4. PartTimeEmployee.verifyHourlyWage() is called.
When CDI is enabled in environment (SE or EE), CDI injection is supported for entity listener classes. If a listener class depends on CDI but CDI is not enabled, it will be ignored.

If a callback method throws an exception and entity manager is joined to transaction, the transaction will be marked for rollback only.

XML Mappings

Equivalent XML mappings of entity listeners for the example above:
<entity-mappings>
    <persistence-unit-metadata>
        <persistence-unit-defaults>
            <entity-listeners>
                <entity-listener class="com.cmobilecom.jpa.example.managed_classes.DefaultListener"/>
            </entity-listeners>
        </persistence-unit-defaults>
    </persistence-unit-metadata>
    
    <mapped-superclass class="com.cmobilecom.jpa.example.managed_classes.Person" >
        <entity-listeners>
            <entity-listener class="com.cmobilecom.jpa.example.managed_classes.PersonListener"></entity-listener>
        </entity-listeners>
    </mapped-superclass>

    <entity class="com.cmobilecom.jpa.example.managed_classes.Employee" >
        <exclude-default-listeners />
        
        <entity-listeners>
            <entity-listener class="com.cmobilecom.jpa.example.managed_classes.EmployeeListener"></entity-listener>
            <entity-listener class="com.cmobilecom.jpa.example.managed_classes.EmployeeListener2"></entity-listener>
        </entity-listeners>
    </entity>

    <entity class="com.cmobilecom.jpa.example.managed_classes.FullTimeEmployee" >
        <exclude-superclass-listeners />
        
        <entity-listeners>
            <entity-listener class="com.cmobilecom.jpa.example.managed_classes.FullTimeEmployeeListener"></entity-listener>
        </entity-listeners>
        
        <pre-persist method-name="verifyBirthday"></pre-persist>
    </entity>

    <entity class="com.cmobilecom.jpa.example.managed_classes.PartTimeEmployee" >
        <pre-persist method-name="verifyHourlyWage"></pre-persist>
    </entity>
    
</entity-mappings>
SubqueryPersistence ContextFrames / No Frames