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_) との 2 つの役に立たない結合がどこから来たのか、および 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;
// ..
}
可能な代替ソリューション? さらにエレガントで、Hibernate を介して正しく変換される可能性がある代替の同等の SQL クエリがあります。
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 で表現する方法がわかりません。