技术开发 频道

处理实体生命周期事件的回调

  【IT168 技术文章】企业应用开发过程中,经常会存在这样的需求:当企业应用中的某些数据被增加、删除、修改时,引发一些特定的动作,完成企业应用中的一些特别的要求,比如企业应用中要完成数据操作日志、处理数据之间的某种关系、或者是完成一些局部的统计工作等。通常情况下,开发者有两种选择:

  开发者提供独立的代码来处理这种需求;

  使用关系型数据库中的“触发器”技术 , 让开发者指定在特定表中添加、删除、修改数据时引发特定的动作,完成数据库中数据的处理。

  然而这两种方式都有一定的局限性,在第 1 种方式中,特别设计的代码和主体程序之间的耦合性较高,无法独立维护,很难复用;第 2 种方式仅仅适用于关系型数据库开发的情况,开发方式比较受局限。

  OpenJPA 中提供了另外一种方式来处理这种特殊的需求,即回调方法。回调方法可以监视实体的整个生命周期,在生命周期的各个时期均可以轻松的加入开发者自己的代码,处理实际业务中的特殊需求。OpenJPA 中目前支持的实体生命周期包括:实体持久化之前、实体可以被持久化、实体被加载之后、实体状态写入数据库之前、实体状态写入数据库之后、实体被删除之前、实体被删除之后。

  OpenJPA 中的回调方法可以在两个层次上实现 :

  在实体类中定义回调方法

  开发者在实体类中编写与实际业务需求相匹配的处理方法,通过注释将这些方法注册到实体生命周期监听机制中,当实体的对应生命周期事件触发时,这些方法将被调用,从而满足用户的特定业务需求。这种方式适用于那些回调方法不太多、业务也不复杂的情况,同时这也不是被推荐的一种编程方式。

  为实体类提供监听器

  开发者除了在实体类中定义回调方法之外,还有一种方式可以将实体的生命周期事件和 Java 方法联系起来,就是使用实体监听器,它使用类似 Awt 或者 Swing 中的监听机制。开发者提供实体监听器,然后将这些监听器注册到合适的实体上,实体成为事件发生的源。当实体生命周期事件触发时,这些被注册的实体监听器将会逐一被激活。使用实体监听器,可以实现监听器的继承、共享、复用,因此能够适用于比简单使用回调方法更复杂的业务环境下。

  实体生命周期相关注释

  OpenJPA 中能够为实体生命周期的多个阶段提供回调支持,包括实体持久化之前、持久化时、被初始化时等。实体生命周期的每一个阶段在 JPA 中都有相应的回调方法注释,这些注释可以在实体类或者实体类的监听器中使用,开发者使用这些注释来指派回调发生时实体类中被调用的方法。

  OpenJPA 中支持的实体生命周期和它们对应的注释如下 :

  属性说明

  javax.persistence.PrePersist使用该注释的方法将在实体被持久化之前被调用。

  被 PrePersist 注释的方法中通常为实体的一些属性提供某种特殊值或者完成某些计算任务,比如开发者可以在 PrePersist 注释的方法中设置实体对象的主键值或者对一些持久化字段的内容进行计算。

  javax.persistence.PostPersist使用 PostPersist 注释的方法在实体设置为可持久化时被调用。

  被 PostPersist 注释的方法中通常完成实体持久化后的一些后续动作,比如在常见的 MVC 模式下,开发者在实体被持久化完成后,使用被 PostPersist 注释的方法完成视图层的更新,另外一种常见的处理是去完成一些额外的数据一致性处理。

  javax.persistence.PostLoad使用 PostLoad 注释的方法在实体的所有提前抓取字段从数据库中完全取出时被调用。

  在被 PostLoad 注释的方法中 , 无法访问到延迟抓取的持久字段的值。在 OpenJPA 中,实体的属性支持提前抓取或者延迟抓取两种策略,提前抓取是指实体属性在实体查询 SQL 执行时就已经从数据库中提取到内存中,延迟抓取是指实体属性一些字段在实体查询 SQL 执行时并没有从数据库中提取到内存中,而是在应用访问到该字段时才从数据库中,延迟抓取主要适用于一些比较大的对象如大字符对象。

  被 PostLoad 注释的方法中通常的业务逻辑就是初始化非持久字段 , 这些非持久化字段的值依赖于实体的其他持久字段的值,比如企业应用中要显示一个用户的图片时,由于图片通常保存在文件系统中,就需要在被 PostLoad 注释的方法中根据用户的信息初始化图片信息。

  javax.persistence.PreUpdate使用 PreUpdate 注释的方法在对象状态被保存到数据库中之前被调用。

  被 PreUpdate 方法注释的方法的业务逻辑通常和被 PostLoad 方法注释的方法中的业务逻辑正好相反。被 PostLoad 注释的方法中使用持久化数据初始化非持久化字段的内容 , 被 PreUpdate 注释的方法中则通常用非持久化数据的内容设置持久化字段的值。

  javax.persistence.PostUpdate使用 PostUpdate 注释的方法在对象状态保存到数据库后调用。

  使用 PostUpdate 注释的方法中处理的业务逻辑一般作用是清除应用层缓存的、过期的数据,避免它们造成对企业应用性能的影响。

  javax.persistence.PreRemove使用 PreRemove 注释的方法在对象被删除的时候调用。

  在被 PreRemove 注释的方法中访问持久字段是不支持的,可以使用该方法实现级连删除 , 或者完成其他清除策略。

  javax.persistence.PostRemove使用 PostRemove 注释的方法在实体对象被删除后调用。

0
相关文章