【问题标题】:Auditing collection of @Embeddables with overridden equals/hashCode in JPA2/Hibernate在 JPA2/Hibernate 中使用覆盖的 equals/hashCode 审计 @Embeddables 的集合
【发布时间】:2013-08-20 20:42:37
【问题描述】:

我有一个 JPA2/Hibernate 设置。此外,这些实体由 Hibernate Envers 审计。我有以下类来表示只有一个字段的邮政编码,即value

仅将任何邮政编码的一个实例保存到Set<PostalCode> 时,一切正常。但是,当我尝试添加另一个邮政编码时,审核失败并出现以下异常:

Caused by: javax.persistence.EntityExistsException: a different object with the same identifier value was already associated with the session: [PostalCodesAudit#{PostOffice_id=5, revision_id=DefaultRevisionEntity(id = 16, revisionDate = Aug 19, 2013 8:50:05 AM), revisionType=ADD}]
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1359)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:80)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:513)
... 58 more

这里奇怪的是它工作正常,当我从 PostalCode 类中删除 equalshashCode 的实现时,该机制工作正常。另外,如果我将集合更改为Set<String>,类似的映射也能完美运行。

我并不是绝对需要在 PostalCode 类中实现 equalshashCode,但我也不太热衷于放弃支持。

映射这种情况的正确方法是什么?

实体

@Embeddable
public class PostalCode {
    @Column(name = "postalCode", length = 5)
    @Pattern(regexp = "[0-9}{5}")
    private String value;

    // Getter and setter for value

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof PostalCode)) {
            return false;
        }
        PostalCode that = (PostalCode) o;
        return new EqualsBuilder().append(this.value, that.value).isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(this.value).toHashCode();
    }
}

在另一个课程中,我尝试将其用作@ElementCollection

@Valid
@ElementCollection(targetClass = PostalCode.class)
@CollectionTable(name="PostalCodes", joinColumns = @JoinColumn(name = "postOffice_id"))
private Set<PostalCode> postalCodes = new HashSet<PostalCode>();

编辑 1

进一步调查显示,如果集合的类型是Collection&lt;PostalCode&gt;List&lt;PostalCode&gt;,即使没有equals/hashCode 实现,审核也会失败:

// No difference in the following
private Collection<PostalCode> postalCodes = new HashSet<PostalCode>();
private Collection<PostalCode> postalCodes = new ArrayList<PostalCode>();

重新 进一步说明,抛出的EntityExistsException 不包含邮政编码的值:仅包含外键、revision_id 和revisionType。

// Excerpt from the exception
PostalCodesAudit#{
    PostOffice_id=5,
    revision_id=DefaultRevisionEntity(id = 16, revisionDate = Aug 19, 2013 11:52:14 AM),
    revisionType=ADD
}

此外,在将字段更改为List&lt;PostalCode&gt; 并使用@OrderColumn 对其进行注释后,无论equals/hashCode 是否实现,审核机制都会正常工作。没有订单列它仍然会中断

@ElementCollection(targetClass = PostalCode.class, fetch = FetchType.LAZY)
@CollectionTable(name = "PostOfficePostalCodes", joinColumns = @JoinColumn(name = "postOffice_id"))
@OrderColumn(name = "listOrder")
private List<PostalCode> postalCodes = new ArrayList<PostalCode>();

【问题讨论】:

    标签: hibernate jpa equals hashcode hibernate-envers


    【解决方案1】:

    我最终通过将字段转换为List&lt;PostalCode&gt; 来解决它,尽管这不是最佳解决方案,因为列表允许重复条目。最终映射如下:

    @ElementCollection(fetch = FetchType.LAZY)
    @CollectionTable(joinColumns = @JoinColumn(name = "postOffice_id"))
    @Column(name = "postalCode", unique = true)
    @OrderColumn(name = "listOrder")
    private List<PostalCode> deliveredPostalCodes = new ArrayList<PostalCode>();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-11
      • 1970-01-01
      • 1970-01-01
      • 2020-06-09
      • 1970-01-01
      • 2011-04-24
      • 1970-01-01
      相关资源
      最近更新 更多