【问题标题】:Compile error when using CriteriaBuilder使用 CriteriaBuilder 时编译错误
【发布时间】:2012-04-30 20:25:09
【问题描述】:

我正在尝试将此 JPA QL 转换为标准生成器。 JBoss 6.0。

"SELECT ba FROM BankAccount ba WHERE ba.balance >= :amt ORDER BY ba.ownerName ASC"

我根据几个教程编写了这段代码。

public List<BankAccount> findWithBalance(int amount) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<BankAccount> cq = cb.createQuery(BankAccount.class);
    Root<BankAccount> from = cq.from(BankAccount.class);

    ParameterExpression<Integer> balance = cb.parameter(Integer.class);
    cq.select(from);

    Predicate predicate = cb.gt(from.get("balance"), balance);
    cq.where(predicate);

    cq.orderBy(cb.asc(from.get("ownerName")));

    TypedQuery<BankAccount> query = em.createQuery(cq);

    return query.getResultList();
}

但是,我在该行中遇到编译错误:

Predicate predicate = cb.gt(from.get("balance"), balance);

错误是:

The method gt(Expression<? extends Number>, Expression<? extends Number>) in the type CriteriaBuilder is not applicable for the arguments (Path<Object>, ParameterExpression<Integer>)

【问题讨论】:

    标签: java generics jpa


    【解决方案1】:

    嗯,我终于找到了调用 gt() 方法的正确方法。这是完整的解决方案。在 JBoss 6 中经过全面测试。

    public List<BankAccount> findWithBalance(int amount) {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<BankAccount> cq = cb.createQuery(BankAccount.class);
        Root<BankAccount> from = cq.from(BankAccount.class);
    
        ParameterExpression<Integer> balance = cb.parameter(Integer.class);
        cq.select(from);
    
        //Here is the trick!
        Predicate predicate = cb.gt(from.<Integer> get("balance"), balance);
    
        cq.where(predicate);
        cq.orderBy(cb.asc(from.get("ownerName")));
    
        TypedQuery<BankAccount> query = em.createQuery(cq);
    
        query.setParameter(balance, amount);
    
        return query.getResultList();
    }
    

    【讨论】:

      【解决方案2】:

      JPA 中的类型安全特性限制了这种与不兼容类型的比较,编译器本身会报错。

      这里from.get("balance")返回的是Path&lt;Object&gt;,但是该方法可以接受java.lang.Number类型的参数,所以会报错。

      你可以试试下面的代码。

      //--
          Metamodel metamodel = em.getMetamodel();
          EntityType<BankAccount> pClass = metamodel.entity(BankAccount.class);
          Predicate predicate = cb.gt(from.get(pClass.getSingularAttribute("balance", Integer.class)), balance);
      //--
      

      如果您使用的是 Metamodel API,那么您可以通过将 ClassName_.field 指定为 cb.gt(from.get(BankAccount_.balance), balance) 来直接检索,这样更简洁且易于调试。

      但是,如果您有许多实体,那么如果 JPA 提供者不生成它们,那么手动编写它们的元模型类可能会很困难。

      【讨论】:

      • 我做了那个改变。新错误是:CriteriaBuilder 类型中的方法 gt(Expression extends Number>, Expression extends Number>) 不适用于参数 (SingularAttribute, ParameterExpression)
      • 我发布了我的答案。请参见上文。
      • @RajV 是的,它好多了 +1
      【解决方案3】:

      编译器抱怨是因为amountint,而不是Expression,看看你是否能弄清楚如何构建一个Expression 这是一个常量并使用它,你应该会很好。

      【讨论】:

      • 您能否使用修改后的代码编辑您的帖子并给出您当前收到的错误消息。如果您使用的是 ParameterExpression 的 arg,我无法想象您会遇到同样的错误。而且这样做可能不是您想要的。
      • 我更新了代码和新的错误信息。我正在做的是直接来自各种教程。我不认为条件查询可以在 JBoss 6 中完成。
      猜你喜欢
      • 1970-01-01
      • 2013-01-01
      • 1970-01-01
      • 2022-01-20
      • 2020-09-19
      • 2015-01-05
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多