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