EJB---->Entity 的生命周期和状态、回调函数
一、四种Entity 的状态:
1. 新实体(new)。Entity 由应用产生,和EJB3 Persistence 运行环境没有联系,也没有唯一的标示符(Identity)。
2. 持久化实体(managed)。新实体和EJB3 Persistence 运行环境产生关联(通过persist(), merge()等方法),在EJB3
Persistence 运行环境中存在和被管理,标志是在EJB3 Persistence 运行环境中有一个唯一的标示(Identity)。
3. 分离的实体(detached)。Entity 有唯一标示符,但它的标示符不被EJB3 Persistence 运行环境管理, 同样的该
Entity 也不被EJB3 Persistence 运行环境管理。
4. 删除的实体(removed)。Entity 被remove()方法删除,对应的纪录将会在当前事务提交的时候从数据库中删除。
当你执行持久化方法,如: persist( ), merge( ), remove( ), find( )或JPQL 查询的时候,实体的生命周期事件将会触发。
1. 新实体(new)。Entity 由应用产生,和EJB3 Persistence 运行环境没有联系,也没有唯一的标示符(Identity)。
2. 持久化实体(managed)。新实体和EJB3 Persistence 运行环境产生关联(通过persist(), merge()等方法),在EJB3
Persistence 运行环境中存在和被管理,标志是在EJB3 Persistence 运行环境中有一个唯一的标示(Identity)。
3. 分离的实体(detached)。Entity 有唯一标示符,但它的标示符不被EJB3 Persistence 运行环境管理, 同样的该
Entity 也不被EJB3 Persistence 运行环境管理。
4. 删除的实体(removed)。Entity 被remove()方法删除,对应的纪录将会在当前事务提交的时候从数据库中删除。
当你执行持久化方法,如: persist( ), merge( ), remove( ), find( )或JPQL 查询的时候,实体的生命周期事件将会触发。
例如,persist( )方法触发数据插入事件,merge( )方法触发数据更新事件,remove( )方法触发数据删除事件,通过JPQL 查询实体会触发数据载入事件。有时实体类得到这些事件发生的通知是非常有用的,例如,你想创建一个日志文件,用来记录数据库每条记录发生的操作(如:添,删,载入等)。持久化规范允许你在实体类中实现回调方法,当这些事件发生时将会通知你的实体对象。当然你也可以使用一个外部类去拦截这些事件,这个外部类称作实体监听者。通过@EntityListeners
注释绑定到实体Bean。
如何在实体类中实现生命周期回调方法及怎样实现一个能拦截实体生命周期事件的实体监听者?
二、生命周期回调事件
如果需要在生命周期事件期间执行自定义逻辑,请使用以下生命周期事件注释关联生命周期事件与回调方法,EJB 3.0 允许你将任何方法指定为回调方法。这些方法将会被容器在实体生命周期的不同阶段调用。
如果需要在生命周期事件期间执行自定义逻辑,请使用以下生命周期事件注释关联生命周期事件与回调方法,EJB 3.0 允许你将任何方法指定为回调方法。这些方法将会被容器在实体生命周期的不同阶段调用。
@PostLoad 事件在下列情况触发
1.执行EntityManager.find( )或getreference( )方法载入一个实体后
2.执行JPQL 查询过后
3.EntityManager.refresh( )方法被调用后
@PrePersist 和@PostPersist 事件在实体对象插入到数据库的过程中发生,@PrePersist 事件在调用EntityManager.persist( )方法后立刻发生,级联保存也会发生此事件,此时的数据还没有真实插入进数据库。@PostPersist 事件在数据已经插入进数据库后发生。
@PreUpdate 和@PostUpdate 事件的触发由更新实体引起,@PreUpdate 事件在实体的状态同步到数据库之前触发,此时的数据还没有真实更新到数据库。@PostUpdate 事件在实体的状态同步到数据库后触发,同步在事务提交时发生。
@PreRemove 和@PostRemove 事件的触发由删除实体引起,@PreRemove 事件在实体从数据库删除之前触发,
即调用了EntityManager.remove()方法或者级联删除时发生,此时的数据还没有真实从数据库中删除。@PostRemove 事件在实体已经从数据库中删除后触发。
1.执行EntityManager.find( )或getreference( )方法载入一个实体后
2.执行JPQL 查询过后
3.EntityManager.refresh( )方法被调用后
@PrePersist 和@PostPersist 事件在实体对象插入到数据库的过程中发生,@PrePersist 事件在调用EntityManager.persist( )方法后立刻发生,级联保存也会发生此事件,此时的数据还没有真实插入进数据库。@PostPersist 事件在数据已经插入进数据库后发生。
@PreUpdate 和@PostUpdate 事件的触发由更新实体引起,@PreUpdate 事件在实体的状态同步到数据库之前触发,此时的数据还没有真实更新到数据库。@PostUpdate 事件在实体的状态同步到数据库后触发,同步在事务提交时发生。
@PreRemove 和@PostRemove 事件的触发由删除实体引起,@PreRemove 事件在实体从数据库删除之前触发,
即调用了EntityManager.remove()方法或者级联删除时发生,此时的数据还没有真实从数据库中删除。@PostRemove 事件在实体已经从数据库中删除后触发。
三、在外部类中实现回调
Entity listeners(实体监听者)用作拦截实体回调事件,通过@javax.persistence.EntityListeners 注释可以把他们绑
定到一个实体类。在Entity listeners 类里,你可以指定一个方法拦截实体的某个事件,所指定的方法必须带有一个Object 参数及返回值为void,格式如下:
void <MethodName>(Object)
通过为方法加上事件注释,即完成特定事件与回调方法的关联。
定到一个实体类。在Entity listeners 类里,你可以指定一个方法拦截实体的某个事件,所指定的方法必须带有一个Object 参数及返回值为void,格式如下:
void <MethodName>(Object)
通过为方法加上事件注释,即完成特定事件与回调方法的关联。
EntityListenerLogger.java
package com.foshanshop.ejb3.bean.listener; import javax.persistence.PostLoad; import javax.persistence.PostPersist; import javax.persistence.PostRemove; import javax.persistence.PostUpdate; import javax.persistence.PrePersist; import javax.persistence.PreRemove; import javax.persistence.PreUpdate; public class EntityListenerLogger { @PostLoad public void postLoad(Object entity) { System.out.println("载入了实体Bean{" + entity.getClass().getName( ) + "}"); } @PrePersist public void PreInsert(Object entity) { System.out.println("对实体Bean{" + entity.getClass().getName( )+ "}调用了 EntityManager.persist()或级联保存"); } @PostPersist public void postInsert(Object entity) { System.out.println("在JDBC API层对实体Bean{" + entity.getClass().getName( )+ "}执行了插 入操作,但事务还未提交"); } @PreUpdate public void PreUpdate(Object entity) { System.out.println("对实体Bean{" + entity.getClass().getName( )+ "}调用了 EntityManager.merge()或级联更新"); } @PostUpdate public void PostUpdate(Object entity) { System.out.println("在JDBC API层对实体Bean{" + entity.getClass().getName( )+ "}执行了更 新操作,但事务还未提交"); } @PreRemove public void PreRemove(Object entity) { System.out.println("对实体Bean{" + entity.getClass().getName( )+ "}调用了 EntityManager.remove()或级联删除"); } @PostRemove public void PostRemove(Object entity) { System.out.println("实体Bean{" + entity.getClass().getName( )+ "}已经从数据库中删除"); } }
我们使用@javax.persistence.EntityListeners 注释把上面的实体监听类绑定到下面的实体中
@javax.persistence.EntityListeners 注释可以绑定多个实体监听类,之间用逗号分隔,监听的顺序按照定义的先后顺序执行。
EntityLifecycle.java
package com.foshanshop.ejb3.bean; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EntityListeners; import javax.persistence.GeneratedValue; import javax.persistence.Id; import com.foshanshop.ejb3.bean.listener.EntityListenerLogger; @Entity @EntityListeners({EntityListenerLogger.class}) public class EntityLifecycle implements Serializable{ private static final long serialVersionUID = 2619167645480125649L; private Integer id; private String name; public EntityLifecycle() {} public EntityLifecycle(String name) { this.name = name; } @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(nullable=false,length=32) public String getName() { return name; } public void setName(String name) { this.name = name; } }EntityLifecycleDAOBean.java
package com.foshanshop.ejb3.impl; import java.util.List; import javax.ejb.Remote; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import com.foshanshop.ejb3.EntityLifecycleDAO; import com.foshanshop.ejb3.bean.EntityLifecycle; @Stateless @Remote (EntityLifecycleDAO.class) @SuppressWarnings("unchecked") public class EntityLifecycleDAOBean implements EntityLifecycleDAO { @PersistenceContext protected EntityManager em; public EntityLifecycle Load() { return em.find(EntityLifecycle.class, 1);//此处将会触发@PostLoad事件 } public void Persist() { EntityLifecycle entitylifecycle = new EntityLifecycle("孙丽"); em.persist(entitylifecycle); } public void Remove() { Query query = em.createQuery("select e from EntityLifecycle e"); List<EntityLifecycle> result = (List<EntityLifecycle>)query.getResultList(); if (result.size()>0){ EntityLifecycle entitylifecycle = result.get(0); em.remove(entitylifecycle); } } public void Update() { Query query = em.createQuery("select e from EntityLifecycle e"); List<EntityLifecycle> result = (List<EntityLifecycle>)query.getResultList(); if (result.size()>0){ EntityLifecycle entitylifecycle = result.get(0); entitylifecycle.setName("张权"); } } }四、在Entity 类中实现回调
除了外部类可以实现生命周期事件的回调,你也可以把回调方法写在Entity 类中。要注意:直接写在Entity 类
中的回调方法不需带任何参数.
@Entity @Table(name = "EntityLifecycle") public class EntityLifecycle implements Serializable{ @PostLoad public void postLoad() { System.out.println("载入了实体Bean{" + this.getClass().getName( ) + "}"); } @PrePersist public void PreInsert() { System.out.println("对实体Bean{" + this.getClass().getName( )+ "}调用了 EntityManager.persist()或级联保存"); } @PostPersist public void postInsert() { System.out.println("在JDBC API层对实体Bean{" + this.getClass().getName( )+ "}执行了插入 操作,但事务还未提交"); } @PreUpdate Jboss EJB3.0 实例教程传智播客(www.itcast.cn)软件培训参考教材 版权所有:黎活明 public void PreUpdate() { System.out.println("对实体Bean{" + this.getClass().getName( )+ "}调用了 EntityManager.merge()或级联更新"); } @PostUpdate public void PostUpdate() { System.out.println("在JDBC API层对实体Bean{" + this.getClass().getName( )+ "}执行了更新 操作,但事务还未提交"); } @PreRemove public void PreRemove() { System.out.println("对实体Bean{" + this.getClass().getName( )+ "}调用了 EntityManager.remove()或级联删除"); } @PostRemove public void PostRemove() { System.out.println("实体Bean{" + this.getClass().getName( )+ "}已经从数据库中删除"); } }