QueryDSL连接生成无效的SQL

时间:2013-05-16 10:14:51

标签: hibernate jpa querydsl

我正在尝试在QueryDSL(JPA,Hibernate提供程序,Oracle数据库)中转换以下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:“COMPANY0 _”。“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中手动运行此查询,则会收到相同的错误。我不明白与公司(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

QCompanyMapping类定义为

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 个答案:

答案 0 :(得分:1)

您应该在连接后使用别名路径。

这些可能会触发其他连接

outPaths.add(QCompanyMapping.companyMapping.companyByCompanyIdSource.count().add(
         QCompanyMapping.companyMapping.companyByCompanyIdTarget.count()));

答案 1 :(得分:1)

如果我改变

  1. “companyMappingSource.companyByCompanyIdSource.count()”to“companyMappingSource.count()”
  2. “companyMappingTarget.companyByCompanyIdTarget.count()”改为“companyMappingTarget.count()”
  3. 在第一个查询的java代码中

    然后它可以工作:

    outPaths.add(companyMappingSource.count().add(companyMappingTarget.count()));