我有一个非常简单的实体,如:
@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()
?
答案 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