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

JPA标准查询急切地使用带有连接的SINGLE查询而不是多个查询获取关联实体

姜宏盛
2023-03-14

我们正在将Hibernate从4.3.11升级到5.2.12的范围内,从Hibernate原生标准转换为JPA标准查询,并发现了不同的行为。以前的Hibernate条件使用带有连接的单个查询来快速获取一对多关联实体,但JPA使用单独的查询来获取每个根实体的关联实体。

我知道我可以像< code > entity root . fetch(" attributes ",JoinType)那样显式设置fetch模式。内心);但是我们需要在一些AbstractDao实现中这样做,这些实现应该适用于任何一对多关联,所以不能显式地设置它。

那么,我可以以某种方式告诉JPA标准在默认情况下使用连接而不是每个根实体的单独查询在单个查询中急切地获取关联实体吗?

代码示例:

    CriteriaBuilder builder = createCriteriaBuilder();
    CriteriaQuery<T> criteriaQuery = builder.createQuery(getEntityClass());
    Root<T> entityRoot = criteriaQuery.from(getEntityClass());

    criteriaQuery.select(entityRoot);
    criteriaQuery.where(builder.equal(entityRoot.get("param1"), "value"));

    return getEntityManager().createQuery(criteriaQuery).getResultList();

共有1个答案

吕征
2023-03-14

您不能以这种方式配置它,但可以实现必要的行为。

正如您在Hibernate 5.2用户指南中所看到的,有几种方法可以应用抓取策略:

  • @获取批注
  • JPQL/HQL查询-获取连接
  • JPA条件查询-FetchParent::fetch
  • JPA实体图-attributeNodes
  • Hibernate配置文件-fetchOverrides

@Fetch注释是应用获取策略的静态方法,而FetchMode。JOIN的工作原理与您所描述的完全相同:

本质上是一种渴望的获取风格。要提取的数据是通过使用 SQL 外连接获取的。

问题是,即使您用< code>@Fetch(FetchMode)标记您的< code>attributes集合。JOIN)注释,它将被覆盖:

我们不使用 JPQL 查询来获取多个部门实体的原因是 FetchMode.JOIN 策略将被查询获取指令覆盖。

要用JPQL查询提取多个关系,必须改用JOIN FETCH指令。

因此,FetchMode。JOIN在通过实体的标识符或自然id直接获取实体时非常有用。

没有FetchP的JPA标准查询::fetch也会这样做。

因为您需要一个抽象DAO的通用解决方案,所以可能的方法是用反射处理所有急切的一对多关联:

    Arrays.stream(getEntityClass().getDeclaredFields())
            .filter(field ->
                    field.isAnnotationPresent(OneToMany.class))
            .filter(field ->
                    FetchType.EAGER == field.getAnnotation(OneToMany.class).fetch())
            .forEach(field ->
                    entityRoot.fetch(field.getName(), JoinType.INNER));

当然,为每个查询调用反射是低效的。您可以从元模型中获取所有加载的< code>@Entity类,处理它们,并存储结果以备将来使用:

    Metamodel metamodel = getEntityManager().getMetamodel();
    List<Class> entityClasses = metamodel.getEntities().stream()
            .map(Type::getJavaType)
            .collect(Collectors.toList());

    Map<Class, List<String>> fetchingAssociations = entityClasses.stream()
            .collect(Collectors.toMap(
                    Function.identity(),
                    aClass -> Arrays.stream(aClass.getDeclaredFields())
                            .filter(field -> 
                                    field.isAnnotationPresent(OneToMany.class))
                            .filter(field -> 
                                    FetchType.EAGER == field.getAnnotation(OneToMany.class).fetch())
                            .map(Field::getName)
                            .collect(Collectors.toList())
            ));
 类似资料:
  • 我通过提示检查了它在EclipseLink中的工作情况: 这个链接http://blog.ringerc.id.au/2012/06/jpa2-is-very-inflexible-with-eagerlazy.html暗示通过Hibernate是不可能的,建议手动获取。但是,我无法理解如何通过HQL或标准来实现它,特别是如何获得不在实体上但仅存在于数据库上的child.parent_id列。即避

  • 问题内容: 怪物编辑:查询现在将运行,但返回错误答案。添加了一个粗略的架构。PatientID不是tblPatientVisits表中的主键,因为同一患者ID可以出现多次。 列出了每个县名,但每个计数(s.countyName)和计数(t.countyname)为1 编辑:我有一个查询,现在运行,但它返回 问题答案: 没有样本数据和理想的结果很难说,但是也许这是您要追求的?

  • 问题内容: 对于开发人员何时使用联接而不是子查询是否有经验法则还是相同的? 问题答案: 取决于RDBMS。您应该比较两个查询的执行计划。 根据我对Oracle 10和11的经验,执行计划始终是相同的。

  • jpaQuery.from(tableA,tableb)。(如何编写以下条件)。id=表格b。id() 如何使用查询dsl编写左向外连接?? 这是编写eq连接的示例代码 JPA query query = new JPA query(em); Q表A = Q表A.QTableB 表 B = QTableB 表 B query.from(tableA, tableB). where(tableA.i

  • 简介 Cabal-DB 的关联数据查询主要用了两个方法:->has('table') 和->belongs('table'), 因为其实数据库关联关系只有两种,一种是拥有(has)另一种是属于(belongs),如: 用户拥有更多个文章 文章拥有多个标签 文章属于一个用户 文章标签关联记录属于一个标签和一篇文章 语法 拥有关系查询语法: $row->has($name, $foreignKeyOr