私はエンティティFooDetailsを持っています。このフィールドには、CustomerフィールドとLocationリストがあります。顧客はアドレス(@OneToOne単方向マッピング)を持ち、ロケーションには@OneToOneマッピングを持つアドレスもあります。Hibernate - 複数のフィールドから同じエンティティへの関係
お客様と住所の住所は同じです。これらのオブジェクトはすべてリモートサービスに由来し、リモートオブジェクトからのIDを保存する前に手動でエンティティに格納します。マッピングは次のようになります。
@Entity
@Table(name = "FOO")
public class FooDetails {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private long id;
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "customer_id")
private Customer customer;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "details_id")
private Set<Location> locationList;
...
}
@Entity
@Table(name = "CUSTOMER")
public class Customer {
@Id
@Column(name = "customer_id", unique = true)
private long customerId;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id")
private Address address;
...
}
@Entity
@Table(name = "LOCATION")
public class Location {
@Id
@Column(name = "location_id", unique = true)
private long locationId;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id")
private Address address;
...
}
@Entity
@Table(name = "ADDRESS")
public class Address{
@Id
@Column(name = "address_id")
private long addressId;
...
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof StawareAddress)) return false;
StawareAddress that = (StawareAddress) o;
return addressId == that.addressId;
}
@Override
public int hashCode() {
return (int) (addressId^(addressId >>> 32));
}
}
webserviceからFooDetailsオブジェクト全体を受け取ると、ローカルデータベースに保存しようとします。
データベースがクリーンであれば(まだ保存されているアドレスはありません)、WSからの適切なIDを持つ1つのアドレスが保存されます。このidを持つアドレスが既に存在する場合、Hibernateは新しいものをデータベースに挿入しようとしますが、addressIdの一意制約のためにエラーが発生します。
私はエンティティを保存するためにSpring Data Jpaを使用しています(save()メソッド)。
私が見逃した明らかなエンティティマッピングの問題は何ですか?
私が知っている解決策の1つですが、避けたいのですが、私はHibernateがそれを処理すべきだと考えています。 save()に渡された分離されたエンティティは、データベースに存在するものと同じである、常に存在する主キーを基にした適切なハッシュコードと等価性を持ちます。なぜカスケードが機能しないのですか? – mdziob
Hashcode/Equalsはこれとは関係ありません。あなたはFooDetails上でPERSIST操作を実行しており、それは子関係、Addressにカスケードされます。明らかに、同じ識別子を持つ新しいアドレスをPERSISTすることはできません。しかし、あなたはマージすることができます。しかし、再び、それはカスケードしているものではありません:)。 – Naros
私はあなたを正しく理解しているかわかりません。私が言及したように、渡されたエンティティがIDを持っているかどうかを調べるspringデータjpaからsave()メソッドを使用しています - もしそうなら、merge(http://stackoverflow.com/questions/16559407/spring-dataのコードスニペット) -jpa-save-new-entity-referencing-existing-one)を指定します。だからマージはカスケードしないのですか? – mdziob