java 使用 CriteriaBuilder 时编译错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10390115/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 00:50:32  来源:igfitidea点击:

Compile error when using CriteriaBuilder

javagenericsjpa

提问by RajV

I am trying convert this JPA QL to criteria builder. JBoss 6.0.

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

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

I wrote this code according to several tutorials.

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

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();
}

But, I am getting a compile error in the line:

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

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

The error is:

错误是:

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

回答by RajV

Well, I finally found the right way to call the gt() method. Here is the complete solution. Fully tested in JBoss 6.

好吧,我终于找到了调用 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();
}

回答by Nayan Wadekar

The type safety feature in JPA restricts such comparisons with incompatible types, the compiler itself will raise error.

JPA 中的类型安全特性限制了与不兼容类型的此类比较,编译器本身会引发错误。

Here, from.get("balance")returns the Path<Object>, but the method can accept parameter of type java.lang.Number, therefore results in error.

此处,from.get("balance")返回Path<Object>,但该方法可以接受类型为 的参数java.lang.Number,因此会导致错误。

You can try the below code.

你可以试试下面的代码。

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

If you are using Metamodel API, then you can retieve directly by specifying ClassName_.field as cb.gt(from.get(BankAccount_.balance), balance)which is much cleaner & easy to debug.

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

But if you are having many entities, then it may be difficult to write their Metamodel classes manually, if the JPA provider doesn't generate them.

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

回答by Francis Upton IV

The compiler is complaining because amountis an int, not an Expression, see if you can figure out how to build an Expressionthat's a constant and use that and you should be good.

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