2017-03-09 8 views
0

私はエンティティ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

ここでは実際にはCascadeType.ALLの使用を控え、手動で処理します。

public void saveFoodetails(FooDetails fooDetails) { 
    Address address = addressRepository.find(fooDetails.getAddress().getId()); 
    if (address != null) { 
    // perhaps you update address with data from fooDetails.getAddress() 
    addressRepository.save(address); 
    // associate attached address instance with fooDetails now. 
    fooDetails.setAddress(address); 
    } 
    else { 
    // save the new incoming address contained in FooDetails 
    addressRepository.save(fooDetails.getAddress()); 
    } 
    // now save/update FooDetails 
    fooDetailsRepository.save(fooDetails);   
} 
+0

私が知っている解決策の1つですが、避けたいのですが、私はHibernateがそれを処理すべきだと考えています。 save()に渡された分離されたエンティティは、データベースに存在するものと同じである、常に存在する主キーを基にした適切なハッシュコードと等価性を持ちます。なぜカスケードが機能しないのですか? – mdziob

+0

Hashcode/Equalsはこれとは関係ありません。あなたはFooDetails上でPERSIST操作を実行しており、それは子関係、Addressにカスケードされます。明らかに、同じ識別子を持つ新しいアドレスをPERSISTすることはできません。しかし、あなたはマージすることができます。しかし、再び、それはカスケードしているものではありません:)。 – Naros

+0

私はあなたを正しく理解しているかわかりません。私が言及したように、渡されたエンティティがIDを持っているかどうかを調べるspringデータjpaからsave()メソッドを使用しています - もしそうなら、merge(http://stackoverflow.com/questions/16559407/spring-dataのコードスニペット) -jpa-save-new-entity-referencing-existing-one)を指定します。だからマージはカスケードしないのですか? – mdziob

関連する問題