0
我有實體FooDetails,它有兩個領域的關係:客戶和位置的列表。客戶具有地址(@OneToOne單向映射),並且位置也具有使用@OneToOne映射的地址。休眠 - 從多個領域同一個實體
它發生在地址客戶和位置是相同的。所有這些對象來自遠程服務,我手動將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地址保存。如果已經有一個帶有這個ID的地址,Hibernate會嘗試將新的一個插入到數據庫中,並且由於addressId上的唯一約束而出現錯誤。
我使用Spring JPA的數據保存實體(save()方法)。
我錯過了什麼明顯的實體映射的問題?
這是我知道的解決方案之一,但我想避免 - 我相信Hibernate應該處理它。傳遞給save()的分離實體具有基於始終存在的主鍵(與數據庫中存在的相同)的正確hashcode&equals。爲什麼級聯不起作用? – mdziob
哈希碼/等於與此無關。您正在FooDetails上執行PERSIST操作,這就是級聯到子關係Address的原因。顯然你不能使用相同的標識符來保存一個新的地址;不過,你可以合併。但是,再次,這不是你在串聯:)。 – Naros
我不知道我是否正確理解你。正如我所提到的,我使用了spring數據jpa中的save()方法,該方法檢查傳遞的實體是否具有ID - 如果是,則調用合併(http://stackoverflow.com/questions/16559407/spring-data中的代碼片段-jpa保存新實體引用現有一)。所以合併不會級聯? – mdziob