我遇到了一个有点奇怪的问题;我有以下的JPA映射:休眠问题@OneToMany @JoinTable和更新操作
@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;
...
而且我做一个简单的测试:
- 坚持一个位置有几个属性
- 变化这些属性之一的名称
- 合并位置返回(与更改的属性)
我的期望(考虑传播)是合并位置只是传播到属性,它会得到更新。发生这种情况(广义上) - 被更改的属性的值确实更新,但是在已经存在映射的连接表中尝试新的INSERT。由于这种新的和不必要的插入,失败(如预期)是:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1-1' for key 'PRIMARY'
现在,罪魁祸首似乎是hashCode
和equals
被implemneted的方式 - 它似乎是,当属性集获得由Hibernate持久化,留存检查集合,如果需要插入每个条目(每个属性):
if (collection.needsInserting(entry, i, elementType))
所以,因为属性没有变化的一个名称,这是现在回升为需要被插入(即我s不是很正确 - 不需要插入,只需要更新) - 因此在连接表中插入操作。我当然可以使用id和hashcode,但这不是Hibernate推荐的方式,而且我宁愿不这样做。 我在映射中可能会导致这种情况吗?这是一个非常标准的映射 - 简单的一对多和简单的合并操作 - 任何建议,使其工作?
任何帮助表示赞赏。
谢谢。
Eugen。
你正在调用哪个Hibernate方法来进行更新('persist'或'merge')? – atrain 2012-07-18 02:55:43
我在调用合并(Spring Data JPA实际上是调用合并)。 – Eugen 2012-07-18 07:01:27