左连接获取重复

时间:2012-12-27 14:43:17

标签: hibernate jpa fetch lazy-evaluation

我在使用JPA(Hibernate)和LazyFetching

时遇到了一些麻烦

我有一些实体: 任务,奖励,合同

关系(都是懒惰的):

  • 追求One2Many奖励; Quest Many2Many Contract;
  • 合同One2Many奖励;合同Many2Many Quest;
  • 奖励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();

我用两个奖励(Reward1,Reward2)

来回忆一个任务

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

2 个答案:

答案 0 :(得分:3)

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

例如,如果您使用条件来获取数据,则可以指定

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

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

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

答案 1 :(得分:0)

一个表可能有更多行,然后是另一个表。所以给出一些避免重复的条件......