5

この 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>)
4

3 に答える 3

13

さて、ついに 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();
}
于 2012-05-03T19:00:01.187 に答える
3

JPA の型安全機能は、互換性のない型とのこのような比較を制限し、コンパイラ自体がエラーを発生させます。

ここでは をfrom.get("balance")返しますPath<Object>が、メソッドは 型のパラメータを受け入れることができる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);
//--

メタモデル API を使用している場合は、ClassName_.field を指定することで直接取得できますcb.gt(from.get(BankAccount_.balance), balance)。これは、はるかにクリーンでデバッグが容易です。

しかし、多数のエンティティーがあり、JPA プロバイダーがエンティティーを生成しない場合、それらのメタモデル クラスを手動で記述するのは難しい場合があります。

于 2012-05-02T21:00:18.807 に答える
0

amountintではなく であるため、コンパイラは不平を言っています。定数であるExpressionを構築してそれを使用する方法を理解できるかどうかを確認してください。Expression

于 2012-04-30T21:12:53.700 に答える