web-dev-qa-db-ja.com

GROUPBYおよびRETURNENTITYLISTを使用したHibernate基準

基準で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();

このコードは、null値のリストを返します。基準でそれを行うことは可能ですか?

8
cz_Nesh

まず、projectonは取得されたデータの量をフィルタリングします。より多くのデータが必要な場合は、それらのプロパティもプロジェクションに追加する必要があります。

例:

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

これで、トランスフォーマーは「Alias to Bean」と言うことを実行し、Java Bean "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 Beanのプロパティ名と一致させてください。

6
Ziul

cz_Nesh。私の最初の答えについて申し訳ありません。私はHibernateAPIを読み、それを見つけたHibernateソースコードをいくつか読みました。このコードを使用する場合

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

listEmpUserImplを返します。このコードを使用する場合

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

listを返しますが、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();

}

public static final ResultTransformer PROJECTIONを見ることができますか?この結果トランスフォーマーは、criteria.setProjectionを使用するときに、setProjection()を呼び出すことによって暗黙的に選択されるという意味です。これは、ResultTransformerが「ROOT_ENTITY」から「PROJECTION」に変更されるため、結果はEmpUserImplをリストしません。 name、oid ..を選択します)。したがって、List EmpUserImplを返したい場合は、set Projections.property( "name")。as( "name")。、(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());
    }

それは動作することができます。お役に立てば幸いです。

4
Jerome

使用できると思います:criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

2
Mazrul