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

Ber*_*Git 5 java hibernate jpa

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

@Entity
public class entityA {

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

    public entityA(){}

}
Run Code Online (Sandbox Code Playgroud)

据我所知,id仅在实体持久化时才设置该值.它是否正确?

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

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

Mag*_*lex 5

如果我在你那里,我会采用 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
    }

}
Run Code Online (Sandbox Code Playgroud)

Java Persistence 2.1 规范解释了如下功能:

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

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


关于实体上有方法来检查其状态的问题,简单的方法是检查该@Id字段null是否存在。如果代码是按书本编写的(即不修改字段本身),那么这将起作用。

然而,有一个更复杂的方法可以实现这一点,正如这个答案中所提出的:

@Transient
private boolean persisted;

@PostLoad
@PostPersist
public void setPersisted() {
  persisted = true;
}
Run Code Online (Sandbox Code Playgroud)

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

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