我的应用程序中有三个实体:客户、价格级别和临时客户价格级别。每个客户都有一个名为defaultPriceLevel的字段,它直接引用PriceLevel。暂时可以将客户切换到其他PriceLevel。为此,添加了一个引用PriceLevel和Customer的TemporalCustomerPriceLever条目。
实体类包括:
@Entity
public class Customer implements Serializable {
...
@ManyToOne
@JoinColumn(name = "default_price_level_id")
private PriceLevel defaultPriceLevel;
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, orphanRemoval = true)
private List<TemporalCustomerPriceLevel> temporalCustomerPriceLevels
= new ArrayList<TemporalCustomerPriceLevel>();
...
}
@Entity
public class PriceLevel implements Serializable {
...
@OneToMany(mappedBy = "priceLevel", cascade = CascadeType.ALL, orphanRemoval = true)
private List<TemporalCustomerPriceLevel> temporalCustomerPriceLevels;
@OneToMany(mappedBy = "defaultPriceLevel", cascade = CascadeType.PERSIST)
private List<Customer> customers;
...
}
@Entity
public class TemporalCustomerPriceLevel implements Serializable {
...
@ManyToOne
@JoinColumn(name = "customer_id")
private Customer customer;
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "price_level_id")
private PriceLevel priceLevel;
...
}
现在我想查询有效价格水平,即如果不存在(有效,为简单起见,省略了)TemporalCustomerPriceLevel,则查询defaultPriceLever,否则查询由Temporal自定义价格水平引用的价格水平。
我使用Spring、JPA(Hibernate)、MySql和Querydsl。在Querydsl中,我编写了以下内容:
QCustomer customer = QCustomer.customer;
QTemporalCustomerPriceLevel qt = QTemporalCustomerPriceLevel.temporalCustomerPriceLevel;
SimpleExpression<PriceLevel> cases = new CaseBuilder()
.when(JPAExpressions.select(qt.count()).from(qt).where(qt.customer.eq(customer)).eq(1L))
.then(
JPAExpressions.select(qt.priceLevel).from(qt).where(qt.customer.eq(customer))
)
.otherwise(
JPAExpressions.select(customer.defaultPriceLevel).from(customer)
).as("activePriceLevel");
JPAQuery<Tuple> query = factory.select(customer, cases).from(customer);
这将导致错误:
antlr.NoViableAltException: unexpected AST node: query
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1367) [hibernate-core-4.3.11.Final.jar:4.3.11.Final]
...
Querydsl生成的查询如下:
select customer,
(case when ((select count(temporalCustomerPriceLevel)
from TemporalCustomerPriceLevel temporalCustomerPriceLevel
where temporalCustomerPriceLevel.customer = customer) = ?1)
then (select temporalCustomerPriceLevel.priceLevel
from TemporalCustomerPriceLevel temporalCustomerPriceLevel
where temporalCustomerPriceLevel.customer = customer)
else (select customer.defaultPriceLevel
from Customer customer)
end) as activePriceLevel
from Customer customer
这似乎有道理。此外,如果我替换这两个
JPAExpressions
行,则查询按预期运行。
因此,主要问题是:在
then
-a的条款
case
块我的Querydsl有什么问题吗?任何帮助都是非常感激的。