【问题标题】:Left join fetching duplication左连接获取重复
【发布时间】:2012-12-27 14:43:16
【问题描述】:

我在使用 JPA(Hibernate) 和 LazyFetching 时遇到了一些问题

我有一些实体: 任务、奖励、契约

关系(都是懒惰的):

  • 任务 One2Many 奖励; Quest Many2Many 合约;
  • 合约One2Many奖励;签订 Many2Many 任务;
  • 奖励Many2One查询;奖励 Many2One 合约;

DB 包含以下数据: Quest1 有 Reward1、Reward2 和 Contract1、Contract2;

在某些情况下,我需要 Quest 及其奖励和合同,所以我在 JPArepository 中这样做:

@Query("select Q from Quest Q left join fetch Q.rewards left join fetch Q.contracts")
List<Quest> getAllQuestsWithRewardsAndContracts();

问题是我收到了
一个任务有 4 个(但它只有 2 个)奖励(Reward1,Reward2,Reward1,Reward2)和两个合同。
我得到了重复的奖励!
我不明白为什么!
如果我这样做:

@Query("select distinct Q from Quest Q left join fetch Q.rewards")
List<Quest> getAllQuestsWithRewardsRew();

我收到一个任务有两个奖励(奖励1,奖励2)

为什么?为什么我有重复?

【问题讨论】:

    标签: hibernate jpa fetch lazy-evaluation


    【解决方案1】:

    这就是 Hibernate 的工作原理。它不会删除由 LEFT OUTER JOINS 生成的重复项。您可以明确指定您需要不同的结果

    例如,如果您使用标准来获取数据,您可以指定

    criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
    

    查看获取数据时生成的 SQL。这是一个常见问题解答,详细解释了为什么 Hibernate 会以这种方式运行 here

    此外,在第一个查询中,您在同一 SQL 中加载多个集合(奖励和合同),这可能会导致笛卡尔积。 Hibernate 有一个 Futures API,它使用比生成笛卡尔积的 SQL 更简单的 SQL 来帮助加载多个子集合。 (我不确定 Futures 是否适用于 JPA)

    【讨论】:

      【解决方案2】:

      一个表的行数可能比另一个表多。所以给一些条件避免重复...

      【讨论】:

        猜你喜欢
        • 2015-08-02
        • 2018-08-24
        • 2012-04-01
        • 2018-03-06
        • 1970-01-01
        • 2011-12-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多