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

获取时的JPA规范连接不起作用(Hibernate、Spring Data JPA)

魏翔
2023-03-14

我将hibernate-orm与spring-data-jpa一起使用。我有三个实体ABC声明如下:

@Entity
public class A {
    @OneToMany(....)
    private List<B> listOfB;
}
@Entity
public class B {
     @ManyToOne(...)
     private A a;
    @OneToMany(...)
    private List<C> listOfC;
}
@Entity
public class C {
    @ManyToOne(...)
    private B b;
}

我的目标是获得A和获取b的列表,在实体C上有一些条件,而不获取它。以下JPQL工作正常。

SELECT a FROM A a
LEFT JOIN FETCH a.listOfB b
LEFT JOIN b.listOfC c
WHERE c.xyz = :xyz

当我尝试使用JPA规范时,我的规范如下所示:

(rootA, query, builder) -> {
    Fetch fetch = rootA.fetch(A_.listOfB, JoinType.LEFT);
    ListJoin listJoin = ((ListJoin)fetch).join(B_.listOfC)
   return builder.equal(listJoin.get(C_.xyz), xyz);
}

我正在重用由fetch操作完成的隐式连接。此连接不符合规范。它输出以下JPQL。

SELECT a FROM A a
LEFT JOIN FETCH a.listOfB b
WHERE c.xyz = :xyz

也就是说,没有别名。

我研究了Hibernate GitHub的源代码。我发现,有一个名为QueryStructure的类。java负责从criteria对象生成JPQL查询。

我找到了渲染获取的函数renderFetches。

@SuppressWarnings({ "unchecked" })
    private void renderFetches(
            StringBuilder jpaqlQuery,
            RenderingContext renderingContext,
            Collection<? extends Fetch> fetches) {
        if ( fetches == null ) {
            return;
        }

        for ( Fetch fetch : fetches ) {
            ( (FromImplementor) fetch ).prepareAlias( renderingContext );
            jpaqlQuery.append( renderJoinType( fetch.getJoinType() ) )
                    .append( "fetch " )
                    .append( ( (FromImplementor) fetch ).renderTableExpression( renderingContext ) );

            renderFetches( jpaqlQuery, renderingContext, fetch.getFetches() );
        }
    }

类似地,有一个函数负责所有连接。

这两个是递归函数,用于呈现标准对象树。

很明显,回迁中的所有连接都被忽略。没有从renderFetches内部调用函数renderJoins,这会导致生成的查询不完整。

有什么深层次的原因可以解释为什么我们不从一个地方加入内部?如果是,那么如何重用fetch完成的现有隐式连接?

这个问题是使用hibernate测试用例模板重新生成的。

  • 重新生成Hibernate测试用例模板

共有1个答案

暴英达
2023-03-14

正如我在问题中提到的,没有来自渲染蚀刻内部的调用,在渲染蚀刻的末尾添加以下内容可以解决问题。

java prettyprint-override">if (fetch instanceof From) {
    From from = (From) fetch;
    renderJoins(jpaqlQuery, renderingContext, from.getJoins());
}

我在hibernate orm中给出了PR HHH-14916。

PR合并将在未来5.6版本中提供。x释放。

 类似资料:
  • 我正在尝试使用Spring数据JPA Specification来查询数据,但这里有一些问题。Java代码如下: 当我注释代码“收件人NoticeJoin.fetch(UserNoticeEntity_. user, JoinType. INNER);”时,它工作正常,但当我取消注释时,我会得到错误: 所以,我想知道使用规范方式是否支持连接获取,或者我的代码有问题。我知道使用@Query(“一些h

  • 为什么它更高效,因为像'your_name'这样的c.name扫描只在第一个查询中发生一次。

  • 我想使用Spring JPA规范连接函数 这是我的表格代码: > } 我如何在规范中加入表中的学生和家长?

  • 试图使用可分页的JOIN FETCH获取Post对象。但是它的抛出异常。 实体 存储库查询如下, 已经尝试过, 但这会导致以下例外。 但下面列出的返回类型工作得很好。为什么以及如何使用分页? 为什么列表按预期工作,但页面对象未按预期工作。是否缺少任何参数,或者是否需要稍微更改查询以适应可分页?

  • 查询DSL: 事实上,这段代码不起作用,我得到以下异常: 问题是条件子句是在方法-中指定的。 Spring Boot 2.0.2 Spring Data JPA 2.0.7 Hibernate5.2.16.final 查询DSL 4.1.4

  • 问题内容: 我有以下通常正常工作的代码: 对于我的许多实体类来说,这都是可行的。但是对于其中的两个它什么也不做,它不会引发任何异常,也不会删除该对象。来自hibernate的日志显示,hibernate执行了许多选择查询,但它甚至没有尝试执行删除。 我已经在这里和这里尝试了在其他类似问题中发现的建议,但是没有用(嗯,后者建议我不能使用,但是我只是在和之间加上了语句)。 我似乎找不到这两个类比其他类