我要解决的问题是避免在休眠状态的list属性内出现重复项。 考虑以下域。
public class Account
{
@OneToMany(fetch = FetchType.LAZY)
@JoinTable(name = "FI_COMPANY_ACCOUNT", joinColumns = @JoinColumn(name = "ACCOUNT_ID", referencedColumnName = "ID"), inverseJoinColumns = @JoinColumn(name = "COMPANY_ID", referencedColumnName = "ID"))
private List<Company> companies;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "account", cascade = CascadeType.ALL, orphanRemoval = true)
private List<AccountDesc> accountDescList;
}
public class Company {}
public class AccountDesc
{
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PARENT_ID", referencedColumnName = "ID")
private Account account;
}
我使用Criteria API提取帐户。在查询中,我使用公司的左联接和accountDescList属性的内部联接执行访存。这有助于我在第一次选择时获得两个属性,并避免了进一步选择。
Root<Account> root = criteriaQuery.from(Account.class);
root.fetch("companies", JoinType.LEFT);
root.fetch("accountDescList");
我知道根实体(此处为Account)可以在结果中重复。我可以使用多种方式解决此问题, http://in.relation.to/2016/08/04/introducing-distinct-pass-through-query-hint/ https://howtoprogramwithjava.com/how-to-fix-duplicate-data-from-hibernate-queries/
但是我面临的问题是,帐户中的属性公司也有重复的实体。如果我们对accountDescList有多个条目,则会发生这种情况。
要解决属性公司中重复项的问题,我认为唯一的解决方案是使用Set。您能否澄清以下问题。
谢谢。
答案 0 :(得分:1)
我认为最好使用Set,因为set不允许元素重复,也可以覆盖Company的equals方法并将其放在两个元素相等时将验证哪些字段。 另一种方法是在setCompanies(List companies)方法中,您可以在此之前做出一些逻辑。companies= companies.stream()。distinct()。collect(Collectors.toList());要么 this.companies =新的ArrayList <>(新的HashSet(companies));
答案 1 :(得分:1)
但是我面临的问题是帐户中的属性公司也有重复的实体。
除非将重复的Company
实体分配给同一帐户,否则不应该发生这种情况。
如this article中所述,在Criteria API查询中使用DISTINCT
将删除根重复项。但是,在您的情况下,不值得在两个@OneToMany
关系上都使用JOIN FETCH,因为这将导致笛卡尔积。
您一次最多只能访存一个馆藏,也许可以对第二个馆藏使用@Subselect
访存。