休眠实体的list属性中的重复项

时间:2018-11-24 01:37:52

标签: java hibernate jpa

我要解决的问题是避免在休眠状态的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。您能否澄清以下问题。

  1. 除了使用Set(针对属性公司)以外,还有其他方法可以解决此问题。
  2. 即使我可以使用,也可以指示休眠使用OrderedSetType(使用LinkedHashSet)。这样我就可以保留从数据库返回的项目顺序。不幸的是,我没有在OrderBy中使用的属性。我需要数据库返回的任何默认顺序。

谢谢。

2 个答案:

答案 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访存。