当前位置: 首页 > 知识库问答 >
问题:

安特尔。带有Querydsl/JPQL/Hibernate的then子句中的子查询出现NoViableAltException

龚勇锐
2023-03-14

我的应用程序中有三个实体:客户、价格级别和临时客户价格级别。每个客户都有一个名为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]
...

查询生成的查询如下所示:

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

这似乎有道理。此外,如果我用fixed PriceLevel对象替换两行< code>JPAExpressions,查询将按预期运行。

所以主要的问题是:在< code>case块的< code > then -子句中使用子查询有什么限制吗?我的查询有什么问题吗?非常感谢任何帮助。

共有1个答案

锺威
2023-03-14

我已经发现下面的替代查询解决了我的问题。尽管如此,如果有人知道tho-子句中的hibernate和JPQL子查询,我仍然会感兴趣。

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()
          )
      )
    );
 类似资料:
  • 记录具有id和名称 带有@Convert的DocumentModel 记录转换器 如果recordIds有多个值(例如:docId=1),即使: 嵌套选择不工作 IN子句有和没有()不工作 子句的成员不工作 导致本机SQL直接无法工作 @公式不工作 而且问题似乎是记录应该是单引号-逗号分隔的,而不仅仅是逗号分隔的,因为它们是字符串。(本机SQL查询在这种情况下工作)

  • 我将以下SQL作为本机查询运行,但我想知道是否有一种方法可以在JPAQuery中运行它,以便使用元组或类实例化。 为了精确起见,我使用了别名而不是qtypes。

  • 问题内容: 我正在尝试使用ORDER BY子句编写JPQL查询: 我想设置一个“ order”参数,其值为“ ASC”或“ DESC”: 然后在我的实现中: 这是当我收到hibernate错误时: 关于我在做什么错的任何想法吗?谢谢! 问题答案: “ ASC”或“ DESC”不能作为查询参数。您可以改用字符串串联。 您应该验证的内容只能是ASC或DESC,而不能直接来自用户。

  • 问题内容: 在MySQL 5.0中,为什么尝试在FROM子句中创建带有子查询的视图时会发生以下错误? 错误1349(HY000):视图的SELECT在FROM子句中包含一个子查询 如果这是MySQL引擎的限制,那么为什么他们还没有实现此功能呢? 此外,对于此限制有什么好的解决方法? 是否有任何变通方法可用于FROM子句中的任何子查询,或者是否存在某些无法在FROM子句中使用子查询无法表达的查询?

  • 我的ParkingLotEntity: 我的Jpa存储库接口 上面的两个方法运行良好,但问题是我还需要从结果集到第二个方法“GetAllParkingLotCurrentlyWorkingInRegionOfRadius”中的位置的任何停车场之间的距离!在SQL Server中,我的定义函数已经计算出了距离。方法2的结果集是成功的,但没有返回距离(这是我的需要),只是一组parkingLotEnt

  • 我去研究了关于JPA2.1规范的信息,这就是我发现的: 用于联接的联接条件来自映射的联接列。这意味着JPQL用户通常不必知道每个关系是如何连接的。在某些情况下,需要在连接条件中附加附加条件,通常是在外部连接的情况下。这可以通过ON子句来实现。ON子句在JPA2.1规范中定义,某些JPA提供程序可能支持ON子句。EclipseLink:Hibernate:TopLink-支持ON子句。 需要注意的是