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

QueryDSL联接生成无效SQL

程英资
2023-03-14

我正在尝试转换QueryDSL (JPA,Hibernate provider,Oracle database)中的以下SQL查询:

select c.id
      , c.name
      , count(coalesce(s.company_id_source, t.company_id_target))
  from company              c
  left join company_mapping s on(s.company_id_source = c.id)
  left join company_mapping t on(t.company_id_target = c.id)
 group 
    by c.id
      ,c.name;

我的java代码:

QCompany company = new QCompany("company");
QCompanyMapping companyMappingSource = new QCompanyMapping("companymappingS");
QCompanyMapping companyMappingTarget = new QCompanyMapping("companymappingT");
JPAQuery query = new JPAQuery(entityManager);
query = query.from(company)
query = query.leftJoin(company.companyMappingsForCompanyIdSource, companyMappingSource);
query = query.leftJoin(company.companyMappingsForCompanyIdTarget, companyMappingTarget);
List<Expression<?>> outPaths = new ArrayList<Expression<?>>();
// add c.id and c.name to outPaths - omitted
outPaths.add(companyMappingSource.companyByCompanyIdSource.count().add(companyMappingTarget.companyByCompanyIdTarget.count()));
// add the group by clause - omitted
List<Object[]> rows = query.listDistinct( outPaths.toArray(new Expression<?>[0]));

它编译得很好,但我得到了一个运行时异常

ORA-00904:“公司_”。“ID”:无效标识符

这是根据Hibernate日志输出生成的查询:

select distinct company0_.ID as col_0_0_, company0_.NAME as col_1_0_, 
count(companymap1_.COMPANY_ID_SOURCE)+count(companymap2_.COMPANY_ID_TARGET) as col_2_0_
from COMPANY company0_ 
left outer join COMPANY_MAPPING companymap1_ on company0_.ID=companymap1_.COMPANY_ID_SOURCE
, COMPANY company3_
left outer join COMPANY_MAPPING companymap2_ on company0_.ID=companymap2_.COMPANY_ID_TARGET
, COMPANY company4_ 
where companymap1_.COMPANY_ID_SOURCE=company3_.ID and companymap2_.COMPANY_ID_TARGET=company4_.ID 
group by company0_.ID , company0_.NAME

如果我在Oracle中手工运行这个查询,我会得到同样的错误。不明白company的两个无用连接(company3_和company4_)从何而来,以及整个where子句。如果我删除这些部分,它可以在Oracle中再次工作。

对查询obj输出调用toString()

select company
from Company company
  left join company.companyMappingsForCompanyIdSource as companymappingS
  left join company.companyMappingsForCompanyIdTarget as companymappingT
where upper(company.name) like ?1 escape '!'
group by company.id, company.name

Q公司映射类定义为

public class QCompanyMapping extends EntityPathBase<CompanyMapping> {
// ..
    public final QCompany companyByCompanyIdSource;

    public final QCompany companyByCompanyIdTarget;
// ..
}

可能的替代解决方案?还有一个替代的等效SQL查询,它看起来更优雅,可以通过Hibernate正确转换:

select c.id
,      c.name
,      count(cm.id)
from   company c
left join company_mapping cm on c.id in (cm.company_id_source, cm.company_id_target)
group by c.id, c.name

但是我不知道如何用QueryDSL来表达。

共有2个答案

阮雅达
2023-03-14

连接后应使用别名路径。

这些可能会触发额外的连接

outPaths.add(QCompanyMapping.companyMapping.companyByCompanyIdSource.count().add(
         QCompanyMapping.companyMapping.companyByCompanyIdTarget.count()));
冯良才
2023-03-14

如果我改变

  1. “公司映射来源.companyByCompanyIdSource.count()”到“公司映射源.count()”
  2. “公司映射目标.companyByCompanyId目标.count()”到“公司映射目标.count()”

在第一个查询的java代码中,它可以工作:

outPaths.add(companyMappingSource.count().add(companyMappingTarget.count()));
 类似资料:
  • 我希望为结果提供内容过滤。我的(为简洁起见而编辑)实体如下所示: 节点: 场景: 来源: 下面是我希望实现的筛选器的一个示例。 给定一个SourceTypes集合,我希望选择所有场景,这样每个场景都会被其中一个类型的源引用。我使用QueryDSL和以下谓词实现了这一点: 一系列这些谓词被组合起来给出一个整体查询。即使只选择一个SourceType,结果查询看起来也是这样: 我相信上面发生的是交叉连

  • Gradle版本:5.1 Java版本:11 我在gradle文件中定义了以下任务来生成QueryDSL类: 下面是我的依赖项块: 如果我执行'gradlew generateQClasses,我会在日志中看到以下内容: 它失败,错误是文件已经存在。如何配置此任务以覆盖文件(如果存在)? 此外,上面的配置是根项目的配置,它有5个子项目。能够覆盖其中一个子项目中的文件,但不能覆盖其他子项目中的文件(

  • 我只想检查一下QueryDSL版本3.1.1。-是否仍然不可能与子查询连接,就像这里的答案所写的:JPQL/querydsl:join subquery and get aliased column

  • 我试图将QueryDSL与Spring Data JPA一起使用。

  • 我正在尝试在我的Spring数据服务中使用查询DSL来实现类似于SQL的查询 成员可以是项目或黑客马拉松的成员。项目是黑客马拉松的一部分。我试图找到哈查顿和子项目的所有成员。 因为谓词产生了交叉连接,所以QueryDslPredicateExecutor接口对我不起作用: 我尝试过使用JPAQuery来手动管理连接策略,但是也遇到了同样的问题: Hibernate:选择memberenti0_.i

  • 我想优化一个queryDSL+Spring数据查询。目前我使用BooleanBuilder作为谓词,这很好,但是它连接了太多的表。我不需要表中的所有列,也不需要某些表。我相信使用投影会减少加入的表的数量。 那么,如何使QueryDSL连接表而不是从所有表中进行选择呢?我尝试优化查询是否正确?投影有意义吗?