为什么 onFlushDirty 将地址检测为脏但在 EmptyInterceptor 中未检测到地址
why onFlushDirty detects address as dirty but not contact in EmptyInterceptor
与休眠配置相关的联系拦截器
public class ContactInterceptor extends EmptyInterceptor {
/**
*/
private static final long serialVersionUID = -2000639365689865828L;
@Override
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) {
if (entity instanceof LastModifiable) {
if (!Arrays.equals(currentState, previousState)) {
int index = ArrayUtils.indexOf(propertyNames, "modified");
if (index > 0) {
currentState[index] = new Date();
return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types);
}
}
}
return false;
}
}
地址模型
public class Address extends Model {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name = "id")
private Long id;
@OneToOne
@JoinColumn(referencedColumnName = "id", name = "contact_id")
private Contact contact;
@Column(name = "address")
private String address1;
@Column(name = "address2")
private String address2;
@Column(name = "city")
private String city;
@Column(name = "country")
private String country;
@Column(name = "state")
private String state;
@Column(name = "zipcode")
private String zipcode;
@Column(name = "company")
private String company;
@Override
public Long getId() {
return this.id;
}
@Override
public void setId(Long val) {
this.id=val;
}
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created", columnDefinition = "DATETIME")
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.modified = this.created = created;
}
private Date created = null;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "modified", columnDefinition = "DATETIME")
public Date getModified() {
return modified;
}
public void setModified(Date modified) {
this.modified = modified;
}
private Date modified;
}
Contact.java
public class Contact extends Model {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Transient
private String fullName;
@Column(name = "email")
private String email;
@Column(name = "contact")
private String contact;
@JsonIgnore
@OneToMany(mappedBy = "contact", fetch = FetchType.EAGER)
protected Set<Address> addresses = new HashSet<Address>(0);
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public Set<Address> getAddresses() {
return addresses;
}
public void setAddresses(Set<Address> addresses) {
this.addresses = addresses;
}
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created", columnDefinition = "DATETIME")
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.modified = this.created = created;
}
private Date created = null;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "modified", columnDefinition = "DATETIME")
public Date getModified() {
return modified;
}
public void setModified(Date modified) {
this.modified = modified;
}
private Date modified;
}
Main.java
public static void main(String[] args) {
HibernateUtility u = new HibernateUtility();
u.beginTransaction();
Contact c = DBService.getDBService(Contact.class).load(112L);
Address add = new Address();
add.setAddress1("Dummy Address 1");
add.setCity("AHMD");
add.setState("GUJ");
add.setCreated(new Date());
add.setCountry("INR");
add.setContact(c);
c.getAddresses().add(add);
// c.setModified(new Date());
u.endTransaction();
}
我们知道 onFlushDirty 是 当 object 被检测到脏时调用 jboss Doc
但是当我在具有类型集合的联系人中添加地址时,在调试期间我可以看到地址是脏的(因为要插入新记录)但是为什么这里的联系人不是脏的?
在集合修改的情况下,hibernate 是否不检测脏 object?还是我遗漏了什么?
我主要关心的是 当 Child 变脏或修改时 parent 修改日期也应该更改 。
- 您忘记调用 em.persist(地址),脏检查仅适用于托管实体。
- 你是不是忘了加hibernate.ejb.interceptor.session_scoped=package.ContactInterceptor 属性??
- 要管理修改日期和创建日期,只需使用@CreationTimestamp、@UpdateTimestamp 和 Hibernate 为您施展魔法 :)
见 Creation timestamp and last update timestamp with Hibernate and MySQL
脏对象是在刷新时得到 saved/updated 的对象,而不是与它们关联的对象。否则,与 Contact
s 关联的所有对象也应被视为脏的,因为它们包含的联系人具有 "changed",然后与这些对象关联的所有对象等有效地意味着可以考虑数据库的很大一部分脏,因为您添加了新地址。
唯一的解决方案是手动编写关联对象更改时执行的逻辑,因为 Hibernate 无法了解应用程序的特定业务规则。
与休眠配置相关的联系拦截器
public class ContactInterceptor extends EmptyInterceptor {
/**
*/
private static final long serialVersionUID = -2000639365689865828L;
@Override
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) {
if (entity instanceof LastModifiable) {
if (!Arrays.equals(currentState, previousState)) {
int index = ArrayUtils.indexOf(propertyNames, "modified");
if (index > 0) {
currentState[index] = new Date();
return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types);
}
}
}
return false;
}
}
地址模型
public class Address extends Model {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name = "id")
private Long id;
@OneToOne
@JoinColumn(referencedColumnName = "id", name = "contact_id")
private Contact contact;
@Column(name = "address")
private String address1;
@Column(name = "address2")
private String address2;
@Column(name = "city")
private String city;
@Column(name = "country")
private String country;
@Column(name = "state")
private String state;
@Column(name = "zipcode")
private String zipcode;
@Column(name = "company")
private String company;
@Override
public Long getId() {
return this.id;
}
@Override
public void setId(Long val) {
this.id=val;
}
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created", columnDefinition = "DATETIME")
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.modified = this.created = created;
}
private Date created = null;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "modified", columnDefinition = "DATETIME")
public Date getModified() {
return modified;
}
public void setModified(Date modified) {
this.modified = modified;
}
private Date modified;
}
Contact.java
public class Contact extends Model {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Transient
private String fullName;
@Column(name = "email")
private String email;
@Column(name = "contact")
private String contact;
@JsonIgnore
@OneToMany(mappedBy = "contact", fetch = FetchType.EAGER)
protected Set<Address> addresses = new HashSet<Address>(0);
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public Set<Address> getAddresses() {
return addresses;
}
public void setAddresses(Set<Address> addresses) {
this.addresses = addresses;
}
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created", columnDefinition = "DATETIME")
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.modified = this.created = created;
}
private Date created = null;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "modified", columnDefinition = "DATETIME")
public Date getModified() {
return modified;
}
public void setModified(Date modified) {
this.modified = modified;
}
private Date modified;
}
Main.java
public static void main(String[] args) {
HibernateUtility u = new HibernateUtility();
u.beginTransaction();
Contact c = DBService.getDBService(Contact.class).load(112L);
Address add = new Address();
add.setAddress1("Dummy Address 1");
add.setCity("AHMD");
add.setState("GUJ");
add.setCreated(new Date());
add.setCountry("INR");
add.setContact(c);
c.getAddresses().add(add);
// c.setModified(new Date());
u.endTransaction();
}
我们知道 onFlushDirty 是 当 object 被检测到脏时调用 jboss Doc
但是当我在具有类型集合的联系人中添加地址时,在调试期间我可以看到地址是脏的(因为要插入新记录)但是为什么这里的联系人不是脏的?
在集合修改的情况下,hibernate 是否不检测脏 object?还是我遗漏了什么?
我主要关心的是 当 Child 变脏或修改时 parent 修改日期也应该更改 。
- 您忘记调用 em.persist(地址),脏检查仅适用于托管实体。
- 你是不是忘了加hibernate.ejb.interceptor.session_scoped=package.ContactInterceptor 属性??
- 要管理修改日期和创建日期,只需使用@CreationTimestamp、@UpdateTimestamp 和 Hibernate 为您施展魔法 :) 见 Creation timestamp and last update timestamp with Hibernate and MySQL
脏对象是在刷新时得到 saved/updated 的对象,而不是与它们关联的对象。否则,与 Contact
s 关联的所有对象也应被视为脏的,因为它们包含的联系人具有 "changed",然后与这些对象关联的所有对象等有效地意味着可以考虑数据库的很大一部分脏,因为您添加了新地址。
唯一的解决方案是手动编写关联对象更改时执行的逻辑,因为 Hibernate 无法了解应用程序的特定业务规则。