やや奇妙な問題が発生しています。次の 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;
...
そして、私は簡単なテストを行っています:
- いくつかの属性を持つ場所を永続化する
- これらの属性のいずれかの名前を変更します
- Location をマージして戻します (変更された属性を使用)
私の期待 (伝播を考慮して) は、場所をマージすると、更新される属性に単純に伝播されるということです。これは (広く) 発生します。変更された属性の値は実際に更新されますが、マッピングが既に存在する結合テーブルで新しい 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 ) )
したがって、属性の 1 つの名前が変更されたため、これは挿入する必要があると見なされます (これは実際には正しくありません - 挿入は必要なく、更新のみが必要です) - したがって、結合テーブルでの挿入操作です。もちろん、equals と hashcode に id を使用することもできますが、それは Hibernate が推奨する方法ではありません。これにつながる可能性のあるマッピングで何かが欠けていますか? これは非常に標準的なマッピングです。単純な 1 対多で単純なマージ操作です。動作させるための提案はありますか?
どんな助けでも大歓迎です。
ありがとう。
オイゲン。