2017-03-09 62 views
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()方法)。

我错过了什么明显的实体映射的问题?

回答

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

这是我知道的解决方案之一,但我想避免 - 我相信Hibernate应该处理它。传递给save()的分离实体具有基于始终存在的主键(与数据库中存在的相同)的正确hashcode&equals。为什么级联不起作用? – mdziob

+0

哈希码/等于与此无关。您正在FooDetails上执行PERSIST操作,这就是级联到子关系Address的原因。显然你不能使用相同的标识符来保存一个新的地址;不过,你可以合并。但是,再次,这不是你在串联:)。 – Naros

+0

我不知道我是否正确理解你。正如我所提到的,我使用了spring数据jpa中的save()方法,该方法检查传递的实体是否具有ID - 如果是,则调用合并(http://stackoverflow.com/questions/16559407/spring-data中的代码片段-jpa保存新实体引用现有一)。所以合并不会级联? – mdziob