JPQL / QueryDSL:加入子查询并获取别名列

时间:2011-08-04 13:16:32

标签: subquery jpql querydsl

我试图通过加入子查询来获得对groupBy的计数的平均值。不知道这是否是正确的方法,但我对mysema doc以外的子查询一无所知。

方案: 客户平均每件产品订单数量是多少? 含义:客户订购产品。因此,客户多次(计数)订购了特定产品。客户为任何产品下达的平均订单数量是多少?

可能听起来有点假设,事实上它只是原型的一部分,但它让我想知道如何使用来自Mysema的花哨的QueryDSL获得在子查询中创建的自定义列的引用。

在SQL中,您只需为count列指定一个别名,然后使用第二个ID列进行连接。 QueryDSL也有“as()”方法,但我不知道,如何检索该列加上我看不出它如何与其他人加入一个查询,因为query.list()只是获取一个列表但是对于某些加入接受它的原因。感觉不对......

这是我的代码:

    JPQLQuery query = createJPQLQuery();

    QOrdering qOrdering = QOrdering.ordering;
    QProduct qProduct = QProduct.product;
    QCustomer qCustomer = QCustomer.customer;           

    // how many of each product did a customer order?
    HibernateSubQuery subQuery = new HibernateSubQuery();
    subQuery.from(qOrdering).innerJoin(qOrdering.product,qProduct).innerJoin(qOrdering.customer, qCustomer);
    subQuery.groupBy(qCustomer,qProduct).list(qCustomer.id,qProduct.id,qProduct.count());

    // get the average number of orders per product for each customer
    query.from(qCustomer);      
    query.innerJoin(subQuery.list(qCustomer.id,qOrdering.count().as("count_orders")));      
    query.groupBy(qCustomer.id);
    return (List<Object[]>) query.list(qCustomer.firstname,subQuery.count_orders.avg());

再次:我如何加入子查询? 如何获得别名“count”列以进行更多聚合,例如avg(我的团队是正确的btw?) 可能是我在这方面有其他一些错误,所以任何帮助表示赞赏!

谢谢!

修改 这就是我希望看到QueryDSL产生的原生SQL:

Select avg(numOrders) as average, cust.lastname from
customer cust
inner join
(select count(o.product_id) as numOrders, c.id as cid, p.name
from ordering o
inner join product p on o.product_id=p.id
inner join customer c on o.customer_id=c.id
group by o.customer_id, o.product_id) as numprods
on cust.id = numprods.cid
group by numprods.cid
order by cust.lastname;

3 个答案:

答案 0 :(得分:13)

不允许在join子句中使用子查询。在JPQL中,子查询仅允许在WHERE和HAVING部分中。 Querydsl JPA查询中的连接方法签名太宽。

由于此查询需要两个级别的分组,可能无法用JPQL / Querydsl JPA表示。

我建议使用Querydsl JPA Native查询支持来编写此查询。

由于Querydsl JPA在内部使用JPQL,因此受到JPQL的表现力的限制。

答案 1 :(得分:0)

我知道这个问题很老,已经有了一个可以接受的答案,但是从this question来看,这似乎仍然令人困扰。看到我在相同问题中的答案。在JoinFlag部分和join()中使用Expression.path()可以实现左连接子查询。希望这对某人有帮助。

答案 2 :(得分:0)

QueryDsl 不支持 join 中的 subQuery,但您可以通过以下方式实现:

我们希望实现以下查询:

select A.* from A join (select aid from B group by aid) b on b.aid=A.id;

将视图或 SQL 查询映射到 JPA 实体:

import lombok.Setter;
import org.hibernate.annotations.Subselect;
import org.hibernate.annotations.Synchronize;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
@Getter
@Setter
@Subselect("select aid from B group by aid")
@Synchronize("B")
public class BGroupByAid {

    @Id
    private Integer aId;
}

然后在类中使用等效的 QueryDSl 实体,就像常规实体一样:

JPAQuery<QAsset> query = new JPAQuery<>(entityManager);  
QBGroupByAid bGroupById = QBGroupByAid.bGroupByAid;

 List<A> tupleOfAssets =
            query.select(A)
        .from(A).innerJoin(bGroupById).on(bGroupById.aId.eq(A.aId))
        .fetchResults()
        .getResults();