获取对象字段前值hibernate JPA

我们假设我有这个课程:

@EntityListeners({MyListener.class}) class MyClass { String name; String surname; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSurname() { return name; } public void setSurname(String name) { this.name = name; } public void save() { JPA.em().persist(this); return this; } public void update() { JPA.em().merge(this); } public static MyClass findById(Long id) { return JPA.em().find(MyClass.class, id); } } 

现在,在我的MyListener类中,我正在尝试找出之前的值MyClass实例与即将保存(更新)到数据库的新值。 我用preupdate metdhod做到这一点:

 @PreUpdate public void preUpdate(Object entity) { ...some logic here...unable to get the old object value in here } 

假设我有一个名称和姓氏的MyClass对象实例:

 MyClass mycls = new MyClass(); mycls.setName("Bob"); mycls.setSurname("Dylan"); mycls.save(); 

这听起来没有,这是好的,因为我只是在听更新。 现在,如果我像这样更新这个实例:

 MyClass cls = MyClass.findById(someLongId) cls.setSurname("Marley"); cls.update(); 

所以这会触发preUpdate中的preUpdate方法,当我尝试:

 MyClass.findById(someLongId); 

当我调试时,我已经获得了新更新的实例,但更新尚未发生,因为当我在列姓中检入数据库时​​,它仍然是Dylan

如何从我的preUpdate方法中获取数据库中的值而不是我刚更新的那个?

我认为一种简单的方法是将先前的值保存在JPA不会持久的瞬态变量中。 因此,只需引入变量previousSurname并在设置器中覆盖它之前保存实际值。

如果要保存多个属性,那么如果您的类MyClassSerializable.则会很容易Serializable.

如果是这样,添加一个post load listener

 public class MyClass implements Serializable { @Transient private transient MyClass savedState; @PostLoad private void saveState(){ this.savedState = SerializationUtils.clone(this); // from apache commons-lang } } 

但请注意savedState是一个分离的实例。

然后,您可以访问EntityListener的先前状态。

您还可以将PostLoad侦听器移动到EntityListener类。 但是,您需要访问savedState字段。 我建议使用包作用域或使用包作用域访问器并将MyClassMyListener放在同一个包中,

 public class MyListener { @PostLoad private void saveState(MyClass myClass){ myClass.saveState(SerializationUtils.clone(myClass)); // from apache commons-lang } } public class MyClass implements Serializable { @Transient private transient MyClass savedState; void saveState(MyClass savedState){ this.savedState = savedState; } }