私のアプリケーションには、Customer、PriceLevel、およびTemporalCustomerPriceLevelという3つのエンティティがあります。各CustomerにはPriceLevelを直接参照するdefaultPriceLevelというフィールドがあります。一時的に、顧客は代替PriceLevelに切り替えることができます。この目的のために、PriceLevelとCustomerの両方を参照するTemporalCustomerPriceLevelへのエントリが追加されます。Querydsl/JPQL/Hibernateを使用したthen節のサブクエリに対するNolr.NoViableAltException
エンティティクラスは以下のとおりです。
@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(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
これは理にかなっているようです。さらに、2つのJPAExpressions
行を固定PriceLevelオブジェクトで置き換えると、クエリは期待どおりに実行されます。
したがって、主な質問は次のとおりです。case
ブロックのthen
- 節にサブクエリを使用する際に制約がありますか?私のQuerydslに何か間違っていますか?どんな助けもありがとうございます。