我需要使用QueryDSL使用公用表表达式构建SQL查询:
WITH cte AS (
SELECT DISTINCT BUSINESS_ID FROM BUSINESS WHERE MERCHANT_CODE like ?
)
SELECT t0.*
FROM PAYMENT t0
LEFT JOIN cte t1 ON t0.PAYER = t1.BUSINESS_ID
LEFT JOIN cte t2 ON t0.PAYEE = t2.BUSINESS_ID
WHERE (t1.BUSINESS_ID IS NOT NULL OR t2.BUSINESS_ID IS NOT NULL)
我有两个JPA实体(付款,业务)。
这是我实施的方式:
String merchantCode = "abcd%";
QPayment payment = QPayment.payment;
QBusiness business = QBusiness.business;
QBusiness cte = new QBusiness("cte");
QBusiness merchant1 = new QBusiness("t1");
QBusiness merchant2 = new QBusiness("t2");
Configuration configuration = new Configuration(new OracleTemplates());
new JPASQLQuery<>(entityManager, configuration)
.with(cte,
JPAExpressions.selectDistinct(business.businessId).from(business)
.where(business.merchantCode.like(merchantCode)))
.select(payment)
.from(payment)
.leftJoin(cte, merchant1).on(payment.payer.eq(merchant1.businessId))
.leftJoin(cte, merchant2).on(payment.payee.eq(merchant2.businessId))
.where(merchant1.businessId.isNotNull()
.or(merchant2.businessId.isNotNull()));
问题是在leftJoin
期间它并不将cte
视为链接,而是插入表名和两个别名:LEFT JOIN BUSINESS cte t1 ON ...
。我尝试了不同的模板 - 没有帮助。
我做错了什么或者是QueryDSL错误?
答案 0 :(得分:1)
JPQL不支持CTE,我们可以在grammar中看到。并且querydsl适用于JPQL。 CTE非常适合特定于供应商,因此您必须执行以下操作之一:
从以上所述我会选择第二个选项。进行本机查询不会损害您的代码。它使您的代码更高效。
答案 1 :(得分:0)
好好看看the tutorial
QCat cat = QCat.cat;
QCat mate = new QCat("mate");
QCat kitten = new QCat("kitten");
query.from(cat)
.innerJoin(cat.mate, mate)
.leftJoin(cat.kittens, kitten)
.list(cat);
您需要.leftjoin(cte.merchant1, merchant1).on(...)
或在父“cte”中调用相应字段的任何内容。
基本上,您需要命名要加入的字段。仅仅陈述元模型是不够的,因为没有办法告诉你实际想要什么。您可以在代码中看到它(以及教程的小猫示例中):您有两个商家想要加入 cte ,那么哪一个是哪个。
.on()
- 子句只是说明了连接有效的条件,就像你可以在那里放置过滤器一样。