Java 获取对象字段以前的值休眠 JPA

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19313629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 16:00:45  来源:igfitidea点击:

Getting object field previous value hibernate JPA

javahibernatecachingjpaannotations

提问by Gandalf StormCrow

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 MyListenerclass I'm trying to figure out the previous value MyClassinstance versus the new value that is about to get saved(updated) to database. I do this with preupdate metdhod :

现在在我的MyListener课堂上,我试图找出以前的值MyClass实例与即将保存(更新)到数据库的新值。我使用 preupdate 方法执行此操作:

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

So assuming I have a MyClassobjects instance with name and surname :

所以假设我有一个MyClass带有 name 和 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 preUpdatemethod in mylistener and when I try to :

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

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.

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

How do I get the value from database in my preUpdatemethod and not the one I just updated?

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

采纳答案by René Link

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.

我认为一种简单的方法是将先前的值保存在 JPA 不会持久化的瞬态变量中。所以只需引入一个变量 previousSurname 并在你在 setter 中覆盖它之前保存实际值。

If you want to save multiple properties it would be easy if your class MyClassis Serializable.

如果你想保存多个属性,如果你的类MyClassSerializable.

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 savedStateis a detached instance.

但请注意,这savedState是一个独立的实例。

You can then access the previous state in your EntityListener.

然后,您可以访问EntityListener.

You can also move the PostLoadlistener to the EntityListenerclass. But then you need access to the savedStatefield. I recommend to make it either package scoped or use a package scoped accessor and put MyClassand MyListenerin the same package,

您还可以将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;
     }

}