Java – get the previous value of the object field hibernate JPA
Let's assume I have this course:
@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 the mylistener class, I try to find out the previous MyClass instance value and the new value to be saved (Updated) to the 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 suppose I have a MyClass object instance with first and last names:
MyClass mycls = new MyClass(); mycls.setName("Bob"); mycls.setSurname("Dylan"); mycls.save();
This doesn't sound good because I'm listening for updates Now, if I update this instance as follows:
MyClass cls = MyClass.findById(someLongId) cls.setSurname("Marley"); cls.update();
So this will trigger the preupdate method in mylistener when I try:
MyClass.findById(someLongId);
When I debug, I have got the newly updated instance, but the update hasn't happened yet, because when I check the database, the column name is still Dylan
How do I get the value of the database from my preupdate method instead of the value I just updated?
Solution
I think a simple way is to save the previous value in a temporary variable, JPA will not persist
If you want to save multiple attributes, it will 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 } }
Note, however, that savedstate is a separate instance
You can then access the previous state in the entitylistener
You can also move the postload listener to the entitylistener class However, you need to access the savedstate field I suggest using it as a scope restriction or using an accessor that encapsulates a scope, and putting 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; } }