web-dev-qa-db-ja.com

POJOへのcreateNativeQueryマッピング(非エンティティ)

一見簡単な問題があります。

entityManager()
.createNativeQuery("select count(*) as total, select sum(field) as total_sum ... blabla") 

そして、私は次のようにPOJOに選択結果を書き込みたいです:

public class AggregateStatsDto {

    private int total;

    private long totalSum;

    // getters, setters, cosntructors
}

これを達成するための最良の方法は何ですか?

私はJPA 2.1を使用できます@ SqlResultSetMapping@ ConstructorResultと組み合わせて使用​​しようとしました:

@SqlResultSetMapping(name = "AggregateStatsResult", classes = {
        @ConstructorResult(targetClass = AggregateStatsDto.class,
                columns = {
                        @ColumnResult(name = "total"),
                        @ColumnResult(name = "totalSum")
                })
})
public class AggregateStatsDto {

        private long total;

        private int totalSum;

        // getters, setters, cosntructors
    }

クエリ:

AggregateStatsDto result = (AggregateStatsDto) entityManager()
    .createNativeQuery("select count(*) as total, select sum(field) as total_sum ... blabla", "AggregateStatsResult")
    .getSingleResult();

しかし、運はありません。とにかく@Entityが欲しいようです。しかし、POJOだけが欲しいのです。

org.hibernate.MappingException: Unknown SqlResultSetMapping [AggregateStatsResult]"

前もって感謝します!

11
fasth

私は次の方法で問題を解決しました:これはクエリです:

  final Query query = Sale.entityManager().createNativeQuery(...);

次に、エンティティマネージャー内の内部Hibernateセッションにアクセスし、スカラー/ resultTransformerを適用しました。それで全部です!

 // access to internal Hibernate of EntityManager
        query.unwrap(SQLQuery.class)
                .addScalar("total", LongType.INSTANCE)
                .addScalar("amountOfSales", LongType.INSTANCE)
                .addScalar("amountOfProducts", LongType.INSTANCE)
                .setResultTransformer(Transformers.aliasToBean(SaleStatsInfo.class));

        ...
        query.getSingleResult();
7
fasth

@SqlResultSetMappingアノテーションを、DTOクラスではなく、実際のエンティティであるクラスに配置します。非エンティティでSqlResultSetMappingに注釈を付けると、エンティティマネージャはマッピングを検出できません。

@SqlResultSetMapping(name = "AggregateStatsResult", classes = {
    @ConstructorResult(targetClass = AggregateStatsDto.class,
            columns = {
                    @ColumnResult(name = "total"),
                    @ColumnResult(name = "totalSum")
            })
})
@Entity
public class SomeOtherClassWhichIsAnEntity {
12
jeff

これは推奨される方法ではありません。より効率的な方法は上記の@SqlResultSetMappingで説明されていますが、よりハードコアなものが必要な場合は、エンティティマネージャーが返すオブジェクトによってエンティティマネージャーの結果にアクセスできます。

例えば ​​:

_ Query q = getEntityManager().createNativeQuery(queryString);
_

q.getSingleResult(); bringを使用してそれをトリガーすると、_Java.util.HashMap_型のオブジェクトを使用して、行ごとに結果にアクセスできます。

例えば:

_    Query q = getEntityManager().createNativeQuery(queryString);
    Java.util.HashMap res =  (Java.util.HashMap) q.getSingleResult();
     for (Object key : res.keySet()) {
         System.out.println(key.toString());
         System.out.println( res.get(key).toString());
     }
_
1
AbstactVersion