我有一个简单的关系,其中一个实体有许多特定于它的地址,定义为:
@Entity
public class Corporation {
@Id
private Long id;
@ElementCollection
@CollectionTable(name = "addresses_table", joinColumns = @JoinColumn(name = "corporation_id"))
private List<Address> addresses = new ArrayList<>();
}
Address
类用@Embeddable
注释。这非常有用,因为公司的每次更新都会删除其所有地址,然后插入新地址。这正是我要寻找的行为。我尝试过的其他选项(OneToMany
,ManyToMany
)导致性能较差,因为我需要跳过箍并且仍然无法获得简单的全部删除+全部插入行为。但是,有一个简单的要求,就是我需要能够通过某些条件查询地址。基本上,这可以归结为一个简单的
findAll(Pageable pageable, Specification spec)
方法。这对于当前和将来的用例就足够了。现在问题来了,可嵌入对象不是
Entity
,因此我无法为其创建Spring数据存储库。我能想到的唯一选择是:Specification
方面做到最佳。如果不能,我仍然可以接受,因为将在其上搜索地址的字段不会改变。 select sth from Corporation c join c.addresses
一样执行一些联接查询,然后根据地址属性限制结果。在这里,我再次不确定这是否行得通,并且像直接通过无论是关于所描述的选项还是用于其他替代方案,任何建议都将不胜感激。
最佳答案
单个表可以映射到不同的类。为什么不创建另一个Address
类(通常是@Entity
类),以便可以为其创建存储库并使用想要使用的Specification
。@Embeddable
Address
可以被视为Corporation
的内部类,用于提供全部删除+全部插入行为。如果您希望域客户端仅处理一个Address
类,则只需在@Embeddable
地址和@Entity
地址之间进行转换。
明智的代码看起来像:
@Entity
public class Corporation {
@Id
private Long id;
@ElementCollection
@CollectionTable(name = "addresses_table", joinColumns = @JoinColumn(name = "corporation_id"))
private List<CorporationAddress> addresses = new ArrayList<>();
public void addAddress(Address address){
addresses.add(new CorporationAddress(address));
}
public List<Address> getAddresses(){
return addresses.stream()
.map(CorporationAddress::toAddress).collect(toList());
}
}
//Or you can put it as the internal static nested class inside Corporation if you like
@Embeddable
public class CorporationAddress {
//Create from Address
public CorporationAddress(Address){
}
//Convert to Address
public Address toAddress(){
}
}
@Entity
public class Address {
}
关于hibernate - 查询存储在单独集合中的@Embeddable对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57177024/