8

JPA2/Hibernateの設定があります。さらに、エンティティは Hibernate Envers によって監査されます。1 つのフィールドのみで郵便番号を表す次のクラスがありますvalue

郵便番号のインスタンスを 1 つだけ保存する場合は、すべて正常に機能します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

equalsここで興味深いのは、クラスの実装とクラスhashCodeから実装を削除するとPostalCode、メカニズムが正常に機能することです。また、コレクションを に変更するとSet<String>、同様のマッピングが完全に機能します。

私はクラスで実装することを絶対に要求されてequalsいるわけではありませんが、サポートをやめることにもあまり熱心ではありません。hashCodePostalCode

この種の状況をマッピングする正しい方法は何ですか?

エンティティ

@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<PostalCode>さらに調査すると、コレクションのタイプがまたはの場合、実装List<PostalCode>がなくても監査が失敗することがわかります。equals/hashCode

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

re さらに、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<PostalCode>アノテーションを付けた後は、実装されている@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>();
4

1 に答える 1

3

List<PostalCode>リストでは重複したエントリが許可されているため、これは最適なソリューションではありませんが、フィールドを a に変換することで解決しました。最終的なマッピングは次のとおりです。

@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>();
于 2013-08-28T05:32:25.690 に答える