为什么onFlushDirty将地址检测为脏但在EmptyInterceptor中没有联系

时间:2016-12-29 07:58:36

标签: java hibernate hibernate-mapping

联系使用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是当检测到某个对象变脏时调用 jboss Doc

但是当我在Contact中添加具有类型集合的地址时,在调试期间我可以看到地址是脏的(因为新记录将要插入)但是为什么联系人在这里不脏?

在收集修改的情况下,hibernate是否检测不到脏对象?或者我错过了什么?

我的主要关注点是当孩子很脏或修改后的父母修改日期也应该更改

2 个答案:

答案 0 :(得分:2)

脏对象是在flush上保存/更新的对象,而不是与它们关联的对象。否则,与Contact关联的所有对象也应该被视为脏,因为它们包含的联系人已经更改了#34;然后与这些对象关联的所有对象等实际上意味着数据库的大部分因为你添加了一个新的地址,可能会被认为是脏的。

唯一的解决方案是手动编写关联对象更改时执行的逻辑,因为Hibernate无法知道应用程序的特定业务规则。

答案 1 :(得分:0)

  1. 您忘记调用em.persist(地址),脏检查只适用于托管实体。
  2. 你没有忘记添加hibernate.ejb.interceptor.session_scoped = package.ContactInterceptor属性??
  3. 管理修改和创建日期只需使用@CreationTimestamp,@ UpdateTimestamp和Hibernate为你做的魔术:) 见Creation timestamp and last update timestamp with Hibernate and MySQL