实体持久化时如何实现回调?

时间:2016-11-02 16:59:36

标签: java hibernate jpa

我有一个非常简单的实体,如:

@Entity
public class entityA {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private Long id;

    public entityA(){}

}

据我所知,仅在实体持久化时才设置值id。这是对的吗?

由于我想将id的值传播给某些观察者,这只有在项目持久化后才有意义。所以我需要在void onPersit()中进行某种回调(类似entityA)。如果实体是持久的,则应自动执行方法entityA.onPersit()。如何实现这个?

(如何)实体可以确定它自己的状态。例如。有某种this.isPersisted()this.isDetached()

2 个答案:

答案 0 :(得分:4)

如果我在哪里,我会使用JPA规范中提供的解决方案@PostPersist注释。您的实体将如下所示:

@Entity
public class entityA {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private Long id;

    public entityA(){}

    @PostPersist
    public void onPersit() {
      // logic to perform after the entity has been persisted
    }

}

Java Persistence 2.1 Specification解释了这样的功能:

  

在实体被持久化或删除后,将为实体调用PostPersist和PostRemove回调方法。这些回调也将在这些操作级联的所有实体上调用。分别在数据库插入和删除操作之后将调用PostPersist和PostRemove方法。这些数据库操作可能直接发生   已经调用了持久化,合并或删除操作,或者它们可能在刷新操作发生后直接发生(可能在事务结束时)。 PostPersist方法中提供了生成的主键值。

如果生成的主键仅在插入数据库后可用,则上述引用也会回答您的问题。您的假设是正确的,但它将在注释@PostPersist的方法中提供。

关于在实体上检查其状态的方法的问题,天真的方法是检查@Id字段是否为null。如果代码是由书写的(即不修改字段本身),这将有效。

然而,正如this answer中提出的那样,实现这一目标更为复杂:

@Transient
private boolean persisted;

@PostLoad
@PostPersist
public void setPersisted() {
  persisted = true;
}

通过使用@PostLoad@PostPersist回调,可确保正确设置persisted字段。同样,您需要确保不要修改此方法之外的字段。 @Transient注释确保该字段不是序列化的候选者,因此不是持久性的。

这些解决方案中的任何一个都可以放在一个抽象的实体类中,以便跨实体重用。

答案 1 :(得分:1)

选项(1):如下所示扩展org.hibernate.EmptyInterceptor课程:

public class MyInterceptor extends EmptyInterceptor {

    //override postFlush() which eill be called after entity is committed into database
    public void postFlush(Iterator iterator) {
        //add your code here
    }

   //You can override other required methods like onDelete(), etc..

}

您需要将interceptor object设置为Hibernate session,如下所示(您需要在常用方法中集中以下逻辑,否则就像样板代码):

MyInterceptor interceptor = new MyInterceptor();
session = HibernateUtil.getSessionFactory().openSession(interceptor);
interceptor.setSession(session);

您可以查看API here

选项(2):实施org.hibernate.event.PostInsertEventListener界面

您可以查看API here