【问题标题】:Duplicate items in a list attribute of JPA and Hibernate entityJPA和Hibernate实体的列表属性中的重复项
【发布时间】:2018-11-24 01:37:52
【问题描述】:

我要解决的问题是避免休眠中列表属性内的重复项。 考虑以下域。

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 中使用的属性。我需要数据库返回的任何默认顺序。

提前致谢。

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    但我面临的问题是Account中的属性公司也有重复的实体。

    除非您将重复的 Company 实体分配给同一帐户,否则不应发生这种情况。

    在 Criteria API 查询中使用 DISTINCT 将删除根重复项。但是,在您的情况下,不值得在两个 @OneToMany 关系上使用 JOIN FETCH,因为这会导致笛卡尔积。

    您一次最多只能获取一个集合,并且可能使用@Subselect 获取第二个集合。

    【讨论】:

    • 感谢弗拉德的回复。我检查并确认没有将重复的公司实体分配给同一个帐户。我真的明白根实体是重复的,并且它的解决方案很好。但是属性(公司)中的重复项真的很困扰我:-)。因此,即使我在一个查询中使用两个 fetch,是否可以重复获取内部属性中的项目?如果是这样,我会选择 Set。
    【解决方案2】:

    我认为使用 Set 要好得多,因为 set 不允许元素重复,您也可以覆盖 Company 的 equals 方法,并将其放在两个元素相等时将验证的字段上。 另一种方法是在 setCompanies(List Companies) 方法中,您可以在 this.companies = Companies.stream().distinct().collect(Collectors.toList()); 之前创建一些逻辑。或者 this.companies = new ArrayList(new HashSet(companies)) ;

    【讨论】:

      猜你喜欢
      • 2010-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-15
      相关资源
      最近更新 更多