我遇到了一个有点奇怪的问题;我有以下 JPA 映射:
@Entity
public class Location {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "LOCATION_ID")
private Long id;
@OneToMany( cascade = { CascadeType.ALL }, fetch = FetchType.EAGER )
@JoinTable( joinColumns = { @JoinColumn( name = "LOCATION_ID" ) },
inverseJoinColumns = { @JoinColumn( name = "ATTRIBUTE_ID" ) } )
private Set<Attribute> attributes;
和:
@Entity
public class Attribute implements IAttributeSupport {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ATTRIBUTE_ID")
private Long id;
@Column(nullable = false) private String name;
@Column(nullable = false) private String value;
...
我正在做一个简单的测试:
- 坚持一个具有一些属性的位置
- 更改这些属性之一的名称
- 将位置合并回来(使用更改后的属性)
我的期望(考虑到传播)是合并位置只会传播到属性,属性会得到更新。这种情况(广泛)发生 - 已更改的 Attribute 的值确实已更新,但随后在已存在映射的 Join Table 中尝试新的 INSERT。由于这个新的和不必要的插入,失败(如预期的那样)是:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1-1' for key 'PRIMARY'
现在,罪魁祸首似乎是方式hashCode
并equals
已实现 - 似乎,当 Hibernate 持久化属性集时,集合持久化器检查是否需要插入每个条目(每个属性):
if ( collection.needsInserting( entry, i, elementType ) )
因此,由于其中一个属性的名称确实发生了变化,现在这被认为需要插入(这并不正确 - 不需要插入,只需更新) - 因此在连接表中插入操作。我当然可以将 id 用于 equals 和 hashcode,但这不是 Hibernate 推荐的方式,我也不想这样做。我是否在映射中遗漏了可能导致此问题的某些内容?这是一个非常标准的映射 - 简单的一对多和简单的合并操作 - 有什么建议可以让它工作吗?
任何帮助表示赞赏。
谢谢。
欧根。