Getting object field previous value hibernate JPA
I think an easy way is to save the previous value in a transient variable that JPA will not persist. So just introduce a variable previousSurname and save the actual value before you overwrite it in the setter.
If you want to save multiple properties it would be easy if your class MyClass
is Serializable.
If so add a 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
}
}
But be aware that the savedState
is a detached instance.
You can then access the previous state in your EntityListener
.
You can also move the PostLoad
listener to the EntityListener
class. But then you need access to the savedState
field. I recommend to make it either package scoped or use a package scoped accessor and put MyClass
and MyListener
in the same package,
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;
}
}
Related videos on Youtube
Mrical Singhal
Updated on June 17, 2022Comments
-
Mrical Singhal almost 2 years
Let's assume I have this class :
@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); } }
Now in my
MyListener
class I'm trying to figure out the previous valueMyClass
instance versus the new value that is about to get saved(updated) to database. I do this with preupdate metdhod :@PreUpdate public void preUpdate(Object entity) { ...some logic here...unable to get the old object value in here }
So assuming I have a
MyClass
objects instance with name and surname :MyClass mycls = new MyClass(); mycls.setName("Bob"); mycls.setSurname("Dylan"); mycls.save();
This wasn't picked up by listener which is ok because I'm listening only to updates. Now if I were to update this instance like so :
MyClass cls = MyClass.findById(someLongId) cls.setSurname("Marley"); cls.update();
So this triggers the
preUpdate
method in mylistener and when I try to :MyClass.findById(someLongId);
When I debug I already get the newly updated instance but the update hasn't happened yet because when I check in database in column surname it's still
Dylan
.How do I get the value from database in my
preUpdate
method and not the one I just updated? -
Mrical Singhal over 10 yearsHi Rene, I don't have @PostLoad in my POJO class. I have it inside my entity listener
-
René Link over 10 yearsOk, than you can move the code to the entity listener. I mean that the EntityListener creates a copy of the object on load and sets the field. Or is there anything that I miss?
-
Mrical Singhal over 10 yearsbut if I move this code to listener class, the instance of listener changes. so if I set the value to listener instance in postload, that instance is null in preupdate
-
raspacorp about 7 years@RenéLink Why is it easier if MyClass is Serializable? I ask this because in the hibernate documentation they have a similar example but they are not implementing Serializable: docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/…
-
raspacorp about 7 years@RenéLink ignore my previous comment, I found the answer. SerializationUtils.clone works only with Serializable objects