当前位置: 首页 > 知识库问答 >
问题:

hibernate连接获取一对多的多个表

郑西岭
2023-03-14

我的数据模型中有以下实体关系。

ERD

实体A:一对多:实体B

实体B:一对多:实体C

实体B:一对多:实体D

Hibernate实体:

public class EntityA {
    
    private Integer id;
    
    @OneToMany
    private List<EntityB> entityBList;
}

public class EntityB {
    
    private Integer id;

    @ManyToOne
    private EntityA entityA;
    
    @OneToMany(fetch=FetchType.LAZY)
    private List<EntityC> entityCList;

    @OneToMany(fetch=FetchType.LAZY)
    private List<EntityD> entityDList;
}

public class EntityC {
    
    private Integer id;
    
    @ManyToOne
    private EntityB entityB;
}

public class EntityD {

    private Integer id;

    @ManyToOne
    private EntityB entityB;
}

要求:我想用实体B的连接获取查询实体C,同时也急切地获取实体D。查询完成后,我希望如果我执行entityC。getEntityB()。getEntityDList(),它不应导致hibernate中的N 1查询问题。

我正在尝试以下JPQL查询:

select ec from EntityC ec 
join fetch ec.entityB eb 
join fetch eb.entityD ed 
where ec.id = :id

这导致结果重复,因为与实体D交叉连接。我得到的不是一个结果,而是n个结果,其中n是实体D列表的大小。

我该如何避免这种情况?有没有办法在JPQL中不交叉连接地获取实体D?

共有1个答案

宋航
2023-03-14

第一件事是在查询中使用DISTINCTJPQL关键字,例如:

TypedQuery<EntityC> query = em.createQuery("SELECT DISTINCT ec FROM EntityC ec JOIN FETCH ec.entityB eb JOIN FETCH eb.entityDList ed WHERE ec.id = :id", EntityC.class);
//                                                 ^^^^^^^^

这将消除重复项,但也会产生副作用,将DISTINCT传递给SQL查询,这不是您想要的。阅读这里的细节,在这里和在这个优秀的答案。长话短说-引用弗拉德·米哈尔恰的答案:

通过将DISTINCT传递给SQL查询,执行计划将执行额外的排序阶段,这会增加开销,而不会带来任何值[…]

解决方案在链接的文章和答案中,但简而言之,如果您使用Hibernate

TypedQuery<EntityC> query = em.createQuery("SELECT DISTINCT ec FROM EntityC ec JOIN FETCH ec.entityB eb JOIN FETCH eb.entityDList ed WHERE ec.id = :id", EntityC.class);
query.setHint("hibernate.query.passDistinctThrough", false);
// -OR-
query.setHint(QueryHints.HINT_PASS_DISTINCT_THROUGH, false); // import org.hibernate.jpa.QueryHints
 类似资料:
  • 问题内容: 我正在尝试使用hibernate条件生成器连接4个表。 下面分别是这些表。 在这4个表中,我想为MySQL执行以下sql脚本: 那么,如何使用Hibernate CriteriaBuilder实现这一目标?请帮助… 预先感谢....... 问题答案: CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQue

  • 我的本机查询将类似于:“select*from a inner join b inner join c on a.ida=b.idb and b.lastname=c.lastname and a.name=c.name” 在hibernate中,如果要连接两个表,可以使用@joincolum,如果要通过表B连接表A和表C,可以使用@joincable。 因此在HQL中查询将看起来像:“from

  • 问题内容: hibernate映射中的默认访存类型是什么? 探索之后我知道的是: 渴望 一对一。 对于一对多来说,这是 懒惰的 。 但是在Eclipse中对其进行测试后,它对所有人都非常渴望。 是否取决于我使用的是JPA还是Hibernate? 问题答案: 这取决于您使用的是JPA还是Hibernate。 根据JPA 2.0规范,默认值为: hibernate的时候,一切都是懒惰的 更新: 最新版

  • 在我的应用程序中,用户和首选项实体之间存在多对多关联。由于连接表需要一个额外的列,因此我必须将其分解为2个一对多的关联: 用户实体: 偏好实体: 用户首选项实体: 为了更新其中一个首选项,我循环浏览用户的一组首选项,并更新值如下: 我已经确认,我试图更新的用户变量在代码运行后确实包含新值。更奇怪的是,当重定向发生时,该值会在网页上更新,但数据库不会更新!这是我用来做更新的代码,这个类用@Trans

  • 我想管理与映射到联接表的实体的关系。因此我有3个实体类:、、。具有注释的和成员。 及其嵌入的密钥: 当我需要带有给定标记的帖子时,我希望使用以下查询: 整件事都在这里: https://github.com/riskop/jpa_hibernate_spring_boot_many_to_many_managed_on_join_table_problem

  • > 我有3个实体用户、应用程序和角色。 null null Role1.getUsers().Add(user);Role1.getUsers().Add(user); role2.getUsers().add(user);role2.getUsers().add(user); user.getApplications().add(app1);user.getApplications().add(