2012-04-30 1 views
3

Je suis en train de convertir ce JPA QL en générateur de critères. JBoss 6.0.Erreur de compilation lors de l'utilisation de CriteriaBuilder

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

J'ai écrit ce code selon plusieurs tutoriels.

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

Mais, je reçois une erreur de compilation dans la ligne:

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

L'erreur est:

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

Répondre

10

Eh bien, j'ai finalement trouvé le bon moyen d'appeler la méthode gt(). Voici la solution complète. Entièrement testé dans 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(); 
} 
0

Le compilateur se plaint parce que amount est un int, pas Expression , voir si vous pouvez comprendre comment construire un Expression c'est une constante et l'utiliser et vous devriez être bon.

+0

Pouvez-vous modifier votre message avec le code révisé et donner le message d'erreur que vous obtenez actuellement. Je ne peux pas imaginer que vous obtenez la même erreur si vous utilisez un argument qui est une expression de paramètre. Et faire cela n'est probablement pas ce que vous voulez. –

+0

J'ai mis à jour le code et le nouveau message d'erreur. Ce que je fais vient directement de divers tutoriels. Je ne pense pas que la requête de critères peut être faite dans JBoss 6. – RajV

3

La fonctionnalité de sécurité de type dans JPA restreint de telles comparaisons avec des types incompatibles, le compilateur lui-même déclenchera une erreur.

Ici, from.get("balance") renvoie le Path<Object>, mais la méthode peut accepter le paramètre de type java.lang.Number, ce qui entraîne une erreur.

Vous pouvez essayer le code ci-dessous.

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

Si vous utilisez l'API métamodèle, vous pouvez retieve directement en spécifiant ClassName_.field comme cb.gt(from.get(BankAccount_.balance), balance) qui est beaucoup plus propre & facile à déboguer.

Mais si vous avez plusieurs entités, il peut être difficile d'écrire leurs classes Metamodel manuellement si le fournisseur JPA ne les génère pas.

+0

J'ai fait ce changement. La nouvelle erreur est: La méthode gt (Expression , Expression ) dans le type CriteriaBuilder ne s'applique pas aux arguments (SingularAttribute , ParameterExpression ) – RajV

+0

@RajV Modifié pour supprimer l'erreur de compilation, mais ne peut pas le tester. –

+0

J'ai posté ma réponse. S'il vous plaît voir ci-dessus. – RajV

Questions connexes