Hibernate @PreUpdate:检查已更改的内容 [英] Hibernate @PreUpdate: check what has been changed
问题描述
问题: 如何检查用@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屋!