Quelques questions de base sur les critères de L'App 2.0

j'ai découvert L'API critères JPA 2.0 aujourd'hui et je veux l'apprendre. Juste allé à travers quelques exemples et essayer de le faire d'une main. J'ai un fruit de table avec des colonnes:

  • id,
  • nom,
  • couleur,
  • taille de,
  • "151950920 goût".

L'ordinaire des trucs:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("fruitManager");
EntityManager em = emf.createEntityManager();

//get the criteria builder
CriteriaBuilder cb = em.getCriteriaBuilder();

CriteriaQuery<Fruit> c = cb.createQuery(Fruit.class);
  1. comment les suivants requête obtenir construit en utilisant des critères:

    select id, name, color where name like 'XY%' and  color='orange'
    

    i. e. comment faire:

    • fetch seulement certaines colonnes,
    • inclure la wild card de la recherche,
    • sont ET, OU, où les conditions.



  2. aussi, il est toujours préférable d'obtenir le compte du résultat avant de récupérer les données réelles. Comment puis-je récupérer le résultat de comptage en premier?

est-ce qu'il y a aussi un endroit où je peux obtenir plus d'exemples sur les 'critères' avec plusieurs types différents de requêtes SQL?

3
demandé sur Piotr Nowicki 2011-10-17 11:51:50

2 réponses

tout d'abord, vous opérez à des entités, pas à des tables, donc je supposerai la cartographie suivante pour le Fruit:

@Entity
public class Fruit {
    @Id int id;
    String name;
    String color;
}

lorsque le résultat se compose de colonnes séparées, l'argument de type à la requête est L'objet[].classe (le résultat sera la Liste de l'Objet[]). Une autre possibilité est D'utiliser Tuple. Vous pouvez construire la requête que vous avez décrite avec ce qui suit. Juste pour être clair sur le type d'argument pour le bien de l'exemple, des variables intermédiaires sont créées pour des prédicats et des Paramétrexpressions. Vous pouvez également les aligner sur la création de la requête.

CriteriaQuery<Object[]> myquery = cb.createQuery(Object[].class);
Root<Fruit> root = myquery.from(Fruit.class);

ParameterExpression<String> nameParamExp = cb.parameter(String.class, "name");
ParameterExpression<String> colorParamExp = cb.parameter(String.class, "color");

Predicate namePredicate = cb.like(root.<String>get("name"), colorParamExp);
Predicate colorPredicate = cb.equal(root.get("color"), nameParamExp);

myquery.multiselect(root.get("id"), root.get("name"), root.get("color"))
        .where(cb.and(namePredicate, colorPredicate));

TypedQuery<Object[]> someFruits = em.createQuery(myquery);
someFruits.setParameter("name", "XY%");
someFruits.setParameter("color", "orange");

someFruits.getResultList();

vous pouvez aussi construire la même requête en insérant tout:

myquery.multiselect(root.get("id"), root.get("name"), root.get("color"))
        .where(cb.and(
                cb.like(root.<String>get("name"), "XY%"),
                cb.equal(root.get("color"), "orange")));

ou utiliser Tuple comme type de résultat:

CriteriaQuery<Tuple> myquery = cb.createQuery(Tuple.class);
Root<Fruit> root = myquery.from(Fruit.class);

myquery.select(cb.tuple(root.get("id").alias("id"),
                        root.get("name").alias("name"),
                        root.get("color").alias("color")))
       .where(cb.and(
                cb.like(root.<String>get("name"), "XY%"),
                cb.equal(root.get("color"), "orange")));

TypedQuery<Tuple> someFruits = em.createQuery(myquery);

for (Tuple t: someFruits.getResultList()) {
    //access your results by alias set in query instead of using array index
    Integer id = t.get("id", Integer.class);
    String name = t.get("name", String.class);
    String color = t.get("color", String.class);
}

si vous optez pour le métamodèle canonique, vous devez suivre la classe dans le même paquet avec vos fruits. C'est à vous de vous écrire par vous-même ou de générer avec certains outils (par exemple avec org.hiberner.jpamodelgen.JPAMetaModelEntityProcessor). Première fois, il est logique d'écrire par vous-même:

@StaticMetamodel(Fruit.class)
public abstract class Fruit_ {
    public static volatile SingularAttribute<Fruit, Integer> id;
    public static volatile SingularAttribute<Fruit, String> color;
    public static volatile SingularAttribute<Fruit, String> name;
}

alors vous pouvez aller pour les arguments fortement dactylographiés et remplacer la requête dans l'ancien exemple de tuple par ce qui suit:

myquery.select(cb.tuple(root.get(Fruit_.id).alias("id"),
                        root.get(Fruit_.name).alias("name"),
                        root.get(Fruit_.color).alias("color")))
       .where(cb.and(
                cb.like(root.get(Fruit_.name), "XY%"),
                cb.equal(root.get(Fruit_.color), "orange")));
10
répondu Mikko Maunu 2011-10-17 08:53:14

vous trouverez le tutoriel de base de l'API critères à http://download.oracle.com/javaee/6/tutorial/doc/gjivm.html .

des exemples peuvent être trouvés à http://www.altuure.com/2010/09/23/jpa-criteria-api-by-samples-part-i / , vérifiez également la partie 2.

3
répondu Rasmus Franke 2011-10-17 08:29:33