Критерии гибернации Использование GROUP BY и RETURN ENTITY LIST

Я пытаюсь использовать GROUP BY в своих критериях. Мне нужно сделать это:

SELECT b FROM Book b GROUP BY volumeCode;

У меня есть следующий код:

    Criteria c = s.createCriteria(Book.class);
    c.setProjection(Projections.projectionList().add(Projections.groupProperty("volumeCode")));
    List<Book> result = c.list();

Но этот критерий возвращает только volumeCodes (список строк). Мне нужно получить список Books. Поэтому я попытался использовать Трансформеры:

    Criteria c = s.createCriteria(Book.class);
    c.setProjection(Projections.projectionList().add(Projections.groupProperty("volumeCode")));
    c.setResultTransformer(Transformers.aliasToBean(Book.class));
    List<Book> result = c.list();

Этот код возвращает список нулевых значений. Можно ли это сделать с помощью критериев?


person cz_Nesh    schedule 15.05.2013    source источник


Ответы (3)


Прежде всего, проекция фильтрует количество извлекаемых данных, если вам нужно больше данных, вы также должны добавить эти свойства в проекцию.

Пример:

c.setProjection( Projections.projectionList()
    .add( Projections.property("id").as("id") )
    .add( Projections.property("descripction").as("description") )
    .add( Projections.groupProperty("volumeCode").as("volumeCode") ));

Теперь преобразователь делает то, что он говорит «Псевдоним для Bean», он соответствует псевдониму свойствам вашего Java-бина «Book.java».

Редактировать:

Без преобразователя, если проекция имеет более одного свойства, результат будет таким:

for(Object[] item:criteria.list()){
    System.out.println( (String)item[0] ); //ID
    System.out.println( (String)item[1] ); //Description
    System.out.println( (String)item[2] ); //Volume code
}

Вот почему вы получали исключение приведения, о преобразователе, попробуйте сопоставить каждый псевдоним с именем свойства вашего java-бина.

person Ziul    schedule 15.05.2013
comment
Привет, Зиул, спасибо за ответ. По вашему совету я получаю список объектов, но Java выдает исключение, когда я пытаюсь передать любой объект из списка в книгу. - person cz_Nesh; 16.05.2013
comment
Эм, я удаляю строку с трансформатором O :-)... После добавления этой строки обратно я все равно получаю список нулевых объектов. - person cz_Nesh; 16.05.2013
comment
Спасибо за редактирование вашего поста. Я не хочу получать только одно свойство, а весь объект. Мне нужно получить тот же список объектов, что и после вызова SELECT b FROM Book b GROUP BY volumeCode, поэтому результат должен быть List‹Book› - person cz_Nesh; 17.05.2013
comment
Затем вам нужно, чтобы преобразователь работал, просто добавьте каждое свойство вашего Bean в проекцию с соответствующим псевдонимом (то же имя для псевдонима и свойства), и он будет работать. - person Ziul; 17.05.2013
comment
Когда вы GROUP BY код тома, не должны ли вы также группировать по всем другим свойствам, идентификатору и описанию? Или поместить их в какую-то функцию агрегации? - person Vlastimil Ovčáčík; 04.04.2016

cz_Неш. извините за мой первый ответ. я прочитал Hibernate api и прочитал исходный код Hibernate, который я нашел. если вы используете этот код

session.createCriteria(EmpUserImpl.class).list();  

он вернет список EmpUserImpl. если вы используете этот код

        criteria.setProjection(Projections.projectionList()
            .add(Projections.groupProperty("company").as("company"))
            .add(Projections.property("name").as("name"))
            .add(Projections.property("company").as("company")));
        List list = criteria.list();

он вернет список, а не список EmpUserImpl, почему? я вижу родительский класс критерия CriteriaSpecification, я нахожу это.

public interface CriteriaSpecification {

/**
 * The alias that refers to the "root" entity of the criteria query.
 */
public static final String ROOT_ALIAS = "this";

/**
 * Each row of results is a <tt>Map</tt> from alias to entity instance
 */
public static final ResultTransformer ALIAS_TO_ENTITY_MAP = AliasToEntityMapResultTransformer.INSTANCE;

/**
 * Each row of results is an instance of the root entity
 */
public static final ResultTransformer ROOT_ENTITY = RootEntityResultTransformer.INSTANCE;

/**
 * Each row of results is a distinct instance of the root entity
 */
public static final ResultTransformer DISTINCT_ROOT_ENTITY = DistinctRootEntityResultTransformer.INSTANCE;

/**
 * This result transformer is selected implicitly by calling <tt>setProjection()</tt>
 */
public static final ResultTransformer PROJECTION = PassThroughResultTransformer.INSTANCE;

/**
 * Specifies joining to an entity based on an inner join.
 *
 * @deprecated use {@link org.hibernate.sql.JoinType#INNER_JOIN}
 */
@Deprecated
public static final int INNER_JOIN = JoinType.INNER_JOIN.getJoinTypeValue();

/**
 * Specifies joining to an entity based on a full join.
 *
 * @deprecated use {@link org.hibernate.sql.JoinType#FULL_JOIN}
 */
@Deprecated
public static final int FULL_JOIN = JoinType.FULL_JOIN.getJoinTypeValue();

/**
 * Specifies joining to an entity based on a left outer join.
 *
 * @deprecated use {@link org.hibernate.sql.JoinType#LEFT_OUTER_JOIN}
 */
@Deprecated
public static final int LEFT_JOIN = JoinType.LEFT_OUTER_JOIN.getJoinTypeValue();

}

Вы можете увидеть общедоступный статический окончательный ResultTransformer PROJECTION? он говорит, что этот преобразователь результата выбирается неявно, вызывая setProjection(), означает, что когда вы используете критерии. выберите имя, oid .. ). поэтому, если вы хотите вернуть список EmpUserImpl, вам нужно установить Projections.property("name").as("name")., (если вам нужно имя, просто установите имя). это мой код.

        Criteria criteria = session.createCriteria(EmpUserImpl.class);
    criteria.setProjection(Projections.projectionList()
            .add(Projections.groupProperty("company").as("company"))
            .add(Projections.property("name").as("name"))
            .add(Projections.property("company").as("company")));
    criteria.setResultTransformer(Transformers.aliasToBean(EmpUserImpl.class));
    List<EmpUserImpl> list = criteria.list();
    for (EmpUserImpl empUserImpl : list) {
        System.out.println(empUserImpl.getName());
    }

это может работать. я надеюсь, что это может помочь вам.

person Jerome    schedule 24.04.2015
comment
Я получаю список всех объектов. Но все поля нулевые. Вы знаете, почему это происходит? - person Manoj Shrestha; 22.12.2018

Я думаю, вы можете использовать: criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

person Mazrul    schedule 20.11.2014
comment
@rayryeng Я сталкиваюсь с той же проблемой, пытаясь получить SELECT p FROM person p GROUP BY personId с использованием критериев, но используя setProjection, он просто преобразует его в sql-эквивалент select distint(personId) from person и возвращает список personId, где мне нужен весь объект человека, а List<Person> list = session.createCriteria("Person","p") .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); возвращает список объектов человека. что касается того, почему и как, надеюсь, это поможет здесь - person Mazrul; 20.11.2014
comment
Добавьте это в свой пост. Сначала мы не знали, почему это помогло вам - person rayryeng; 20.11.2014