antlr.NoViableAltException for subquery in then-clause with Querydsl / JPQL / Hibernate
我的应用程序中有三个实体,Customer,PriceLevel和TemporalCustomerPriceLevel。每个客户都有一个名为defaultPriceLevel的字段,该字段直接引用PriceLevel。可以暂时将客户切换到另一个PriceLevel。为此,向TemporalCustomerPriceLevel添加了一个条目,该条目同时引用PriceLevel和客户。
实体类为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | @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; ... } |
我现在要查询有效价格水平,即。 e。如果没有,则为defaultPriceLevel(活动,为简单起见,省略)TemporalCustomerPriceLevel,否则存在TemporalCustomerPriceLevel引用的PriceLevel。
我使用Spring,JPA(休眠),MySql和Querydsl。在Querydsl中,我编写了以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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); |
这会导致错误:
1 2 3 | 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生成的查询如下所示:
1 2 3 4 5 6 7 8 9 10 11 | 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 |
这似乎是有道理的。此外,如果我用固定的PriceLevel对象替换了两个
因此,主要问题是:在
我已经解决了以下替代查询可以解决我的问题。 不过,如果有人知道当时的休眠和JPQL子查询,我仍然会感兴趣。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | JPAQueryFactory factory = new JPAQueryFactory(em); QCustomer customer = QCustomer.customer; QPriceLevel priceLevel = QPriceLevel.priceLevel; QTemporalCustomerPriceLevel tmp = new QTemporalCustomerPriceLevel("tmp_qtcpl"); Date now = new Date(); JPAQuery<Tuple> query = factory.select(customer, priceLevel).from(customer, priceLevel).where( JPAExpressions.select(tmp).from(tmp) .where(tmp.validAfter.loe(now) .and(tmp.validUntil.after(now) .and(tmp.priceLevel.eq(priceLevel) .and(tmp.customer.eq(customer))))).exists() .or( customer.defaultPriceLevel.eq(priceLevel) .and( JPAExpressions.select(tmp).from(tmp) .where(tmp.validAfter.loe(now) .and(tmp.validUntil.after(now) .and(tmp.customer.eq(customer)))).notExists() ) ) ); |