Hibernate @PreUpdate:检查已更改的内容 [英] Hibernate @PreUpdate: check what has been changed

查看:76
本文介绍了Hibernate @PreUpdate:检查已更改的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题: 如何检查用@PreUpdate注释的方法中哪些字段已更改?

Question: How to check which fields has been changed inside method annotated with @PreUpdate?

可选:如果上述问题的答案是不可能,那么也许还有其他方法可以解决我的问题"

我要每次我们更改其中的内容时都会自动更新modified Tourist的字段.

I want automatically update modified Tourist's field each time we change something in it.

情况除外.表示如果仅更改location-应该保留它,但不能更改modified.

Except the situation when we modify only location. Means if we change location only - it should be persisted, but modified mustn't be changed.

已经存在的代码:

@Entity
public class Tourist {

  private long id;
  private String firstName;
  private String lastName;
  private Date created;
  private Date modified;
  private String location;

  @PreUpdate
  public void preUpdate() {
     modified = new Date(); //PROBLEM : change modified even if only location field has been changed!
  }   
  ....
}


更新:经过一些调查,我发现我可以借助拦截器(扩展EmptyInterceptor)解决该问题:


Updated: After some investigations I found that I can solve it with help of interceptors (extend EmptyInterceptor):

public class TouristInterceptor extends EmptyInterceptor{

    Session session;
    private Set updates = new HashSet();

    public void setSession(Session session) {
        this.session=session;
    }

    public boolean onFlushDirty(Object entity,Serializable id,
        Object[] currentState,Object[] previousState,
        String[] propertyNames,Type[] types)
        throws CallbackException {

        if (entity instanceof Tourist){
            if (somethingChangedExceptLocation()) 
                updates.add(entity);
        }
        return false;
    }

但是这种方法的缺点是在需要拦截单个实体时会拦截所有内容.

But disadvantage of this approach is to intercept everything when you need to intercept the single entity.

更新的问题:

  • 如何仅拦截游客实体的同花顺电话?
  • 在事件的帮助下是否可以做同样的事情?表示PreUpdateEvent包含新旧状态
  • How to intercept only Tourist entity flush calls?
  • Is that possible to do the same with help of events? Means PreUpdateEvent which contains new and old state

推荐答案

有一个简单的非JPA解决方案,如下所示,但是它具有一些重复的代码,但是在没有太多字段的情况下是一种解决方案:

There is a simple non-JPA solution which is as follows but which which does have some repetitive code but is a solution when you do not have too many fields:

@Entity
public class Tourist {

    private long id;
    private String firstName;
    private String lastName;
    private Date created;
    private Date modified;
    private String location;

    public void setFirstName(String firstName){
        if(! this.firstName.equals(firstName){
            modified = new Date();
        }

        this.firstName = firstName;
    }

    public void setLastName(String lastName){
        if(! this.lastName.equals(lastName){
            modified = new Date();
        }

        this.lastName= lastName;
    }
}

否则,我会按照另一个答案中的建议,以一种更简洁的方式将以前的状态保存在负载中.

Otherwise I would go with saving the previous state on load as suggested in another answer but in a slightly cleaner way.

@Entity
public class Tourist {

  private long id;
  private String firstName;
  private String lastName;
  private Date created;
  private Date modified;
  private String location;

  @Transient
  private Tourist previousState;

  @PostLoad 
  public void setPreviousState(){
    previousState = new Tourist();
    //copy fields
  }

  @PreUpdate
  public void preUpdate() {
     if(isModified){
        modified = new Date();
     }
  }   

  private boolean isModified(){
    boolean modified = false;

    if(! firstName.equals(previousState.firstName){
        modified = true;
    }

    //check other fields

    return modified;
  }
}

这篇关于Hibernate @PreUpdate:检查已更改的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆