让应用程序响应持久化机制内发生的某些事件往往很有用。这允许实现某种通用功能和扩展内置功能。JPA 规范为此目的提供了两种相关的机制。
@Entity
@EntityListeners(class=Audit.class)
public class Cat {
@Id private Integer id;
private String name;
private Calendar dateOfBirth;
@Transient private int age;
private Date lastUpdate;
//getters and setters
/**
* Set my transient property at load time based on a calculation,
* note that a native Hibernate formula mapping is better for this purpose.
*/
@PostLoad
public void calculateAge() {
Calendar birth = new GregorianCalendar();
birth.setTime(dateOfBirth);
Calendar now = new GregorianCalendar();
now.setTime( new Date() );
int adjust = 0;
if ( now.get(Calendar.DAY_OF_YEAR) - birth.get(Calendar.DAY_OF_YEAR) < 0) {
adjust = -1;
}
age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR) + adjust;
}
}
public class LastUpdateListener {
/**
* automatic property set before any database persistence
*/
@PreUpdate
@PrePersist
public void setLastUpdate(Cat o) {
o.setLastUpdate( new Date() );
}
}
回调方法可以引发 RuntimeException
。如果有当前事务,则必须回滚。已定义了以下回调
回调方法不得调用 EntityManager
或 Query
方法!
你可以在不同层级的实体上定义多个实体监听程序。也可以在不同层级上定义多个回调。但不能在同一实体或同一实体监听程序中为同一事件定义两个监听程序。
可以使用 @ExcludeSuperclassListeners
停止实体监听程序继承,这样将忽略所有超类的 @EntityListeners
。
JPA 规范允许通过 JPA 部署描述符覆盖注释。另外,还有一个可能有用的功能: 默认事件监听程序。
<?xml version="1.0" encoding="UTF-8"?>
<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 orm_2_0.xsd"
version="2.0"
>
<persistence-unit-metadata>
<persistence-unit-defaults>
<entity-listeners>
<entity-listener class="org.hibernate.ejb.test.pack.defaultpar.IncrementListener">
<pre-persist method-name="increment"/>
</entity-listener>
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>
<package>org.hibernate.ejb.test.pack.defaultpar</package>
<entity class="ApplicationServer">
<entity-listeners>
<entity-listener class="OtherIncrementListener">
<pre-persist method-name="increment"/>
</entity-listener>
</entity-listeners>
<pre-persist method-name="calculate"/>
</entity>
</entity-mappings>
你可以在给定实体上覆盖实体监听程序。实体监听程序对应于给定类,并且一个或多个事件都会触发给定的方法调用。你也可以在实体本身上定义事件以描述回调。
版权所有 © 2005 Red Hat Inc. 及各作者