如何使用实体监听器
在实体类中同时提供处理实体生命周期回调方法的代码不是很优雅的编程方式,开发者通常考虑使用非持久的监听器类处理回调方法。OpenJPA 中支持使用实体监听器处理实体的回调方法 , 而不是直接在实体类中处理回调方法。
在 OpenJPA 中,实体监听器类需要提供一个 public 的无参数构造器,其他要求和在实体类中定义回调方法一样 , 一个监听器类同样可以处理多种回调,只需要为监听器中的方法提供回调方法对应的注释如 javax.persistence.PrePersist、javax.persistence.PostPersist 等。特别的是,监听器中的每一个回调方法必须有一个 java.lang.Object 类型的参数,该参数对应的对象代表了触发当前事件的实体对象。
我们可以使用下面的代码创建一个实体监听器类。
清单 5. 创建一个实体监听器类
2. public AnimalListener(){
3. }
4.
5. /**
6. * logPrePersist方法处理实体生命周期中的PrePersist[实体被持久化之前]事件
7. */
8. @PrePersist
9. public void logPrePersist(Object entity){
10. System.out.println("实体将会被持久化.");
11. }
12.
13. /**
14. * logPostPersist方法处理实体生命周期中的PostPersist[实体可以被持久化]事件
15. */
16. @PostPersist
17. public void logPostPersist(Object entity){
18. System.out.println("实体可以被持久化了.");
19. }
20.
21. … // 可以为实体监听器提供更多方法,处理实体的更多回调事件。
22.
23. }
创建实体监听器后,开发者将实体监听器注册到需要被监听的实体中,使用 javax.persistence.EntityListeners 注释可以为实体注册监听器,这个注释支持同时为实体类设置多个监听器 , 只需要在注释的属性中提供多个参数,各参数之间使用”,”隔开。我们可以使用下面的代码为实体注册一个或者多个监听器类。
清单 6. 为实体注册一个或者多个监听器类
2. public class Animal{
3. …
4. }
实体监听器继承层次
由于 OpenJPA 中实体是支持继承的,实体之间的监听器也被实体的子类继承下来,这些实体监听器方法在被触发时的遵循下面的调用顺序:
首先,默认的监听器首先被调用,默认的监听器是指在包注释中定义的监听器;
接下来 , 实体监听器按照继承层次顺序被调用 , 父类监听器在子类监听器之前被调用;
最后 , 如果一个实体的同一个回调事件要触发多个监听器的话 , 这些监听器按照声明的先后顺序被调用;
开发者可以选择屏蔽在父类或者包中声明的监听器,只需要使用下面两个类级别的注释 :
javax.persistence.ExcludeSuperclassListeners 为实体类提供 javax.persistence.ExcludeSuperclassListeners 注释,可以屏蔽所有当前实体类的所有父类中声明的实体监听器。
javax.persistence.ExcludeDefaultListeners 为实体类提供 javax.persistence.ExcludeDefaultListeners 注释,可以屏蔽当前实体类和它所有子类的所有默认监听器。
总结
企业应用中经常有一些特别的需求:在某一个数据被处理的时候,需要引发一连串的操作,OpenJPA 中提供实体生命周期事件回调机制为这种需求提供了更好的解决方案,OpenJPA 中实体生命周期能够支持实体被持久化之前、实体可以被持久化、实体状态写入数据库之前、实体状态写入数据库之后、实体被加载、实体被删除之前、实体被删除之后共 7 种事件,开发者可以根据需要选择为其中的一个或者多个事件编写回调方法。本文中结合简单的例子描述了如何通过 OpenJPA 提供简单的注释、结合 Java 方法就可以监听、处理实体生命周期事件回调的过程。