我有一个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
奇怪的是,它运行良好,当我从
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>();
回覆
另外请注意,抛出的
EntityExistsException
不包含邮政编码的值:仅包含外键,version_id和versionType。// 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
,审核机制都将毫无例外地工作。没有order列仍然会中断@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>();
最佳答案
我最终通过将字段转换为List<PostalCode>
来解决它,尽管这不是最佳解决方案,因为列表允许重复的条目。最终映射如下:
@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>();