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
いるわけではありませんが、サポートをやめることにもあまり熱心ではありません。hashCode
PostalCode
この種の状況をマッピングする正しい方法は何ですか?
エンティティ
@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>();