Некоторые основные вопросы по критериям из JPA 2.0 - PullRequest
4 голосов
/ 17 октября 2011

Сегодня я обнаружил API критериев JPA 2.0 и хочу его изучить. Просто просмотрел несколько примеров и попытался разобраться. У меня есть стол с фруктами с колоннами:

  • id,
  • имя,
  • цвет,
  • размер,
  • вкус.

Обычные вещи:

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. Как будет построен следующий запрос с использованием критериев:

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

    т.е. как:

    • получить только некоторые столбцы,
    • включает поиск по шаблону,
    • включает И, ИЛИ, где условия.

  2. Кроме того, всегда лучше сначала подсчитать результат, прежде чем получать фактические данные. Как я могу сначала получить результат подсчета?

Также есть ли место, где я могу получить больше примеров «критериев» с несколькими различными типами SQL-запросов?

Ответы [ 2 ]

11 голосов
/ 17 октября 2011

Во-первых, вы работаете с сущностями, а не с таблицами, поэтому я предполагаю следующее сопоставление для фрукта:

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

Когда результат состоит из отдельных столбцов, аргумент типа для запроса - Object []. Class (результатом будет список объектов []).Другая возможность - использовать Tuple.Вы можете построить запрос, который вы описали с помощью следующего.Просто для ясности о типе аргумента для примера, промежуточные переменные созданы для Предикатов и ParameterExpressions.Вы также можете включить их в создание запроса.

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

Вы также можете построить тот же запрос, вставив все:

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")));

Или использовать Tuple в качестве типа результата:

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

Если вы выберете каноническую метамодель, то вам нужен следующий класс в одной упаковке с вашим фруктом.Вы сами пишете это или генерируете с помощью какого-либо инструмента (например, с помощью org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor).В первый раз имеет смысл написать это самостоятельно:

@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;
}

Затем вы можете перейти к строго типизированным аргументам и заменить запрос в предыдущем примере кортежа следующим:

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")));
3 голосов
/ 17 октября 2011

Базовое руководство по API критериев можно найти на http://download.oracle.com/javaee/6/tutorial/doc/gjivm.html.

Примеры можно найти на http://www.altuure.com/2010/09/23/jpa-criteria-api-by-samples-part-i/, также проверьте часть 2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...