web-dev-qa-db-fra.com

mappage createNativeQuery sur POJO (non-entité)

J'ai un problème facile au premier abord:

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

Et je veux écrire un résultat de sélection dans POJO, comme ceci:

public class AggregateStatsDto {

    private int total;

    private long totalSum;

    // getters, setters, cosntructors
}

Quel est le meilleur moyen d'y parvenir?

Je peux utiliser JPA 2.1 et essayé d'utiliser @SqlResultSetMapping en conjonction avec @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
    }

Question:

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

Mais pas de chance. Il semble qu’il veuille de toute façon de @Entity. Mais je veux juste un POJO.

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

Merci d'avance!

7
fasth

J'ai résolu mon problème de la manière suivante: Ceci est une requête:

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

Ensuite, j'ai accédé à la session interne Hibernate à l'intérieur du gestionnaire d'entités et appliqué les scalaires/resultTransformer. C'est tout!

 // 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();
6
fasth

Placez votre annotation @SqlResultSetMapping dans une classe qui est une entité réelle et non dans la classe DTO. Votre responsable d'entité ne peut pas découvrir votre mappage lorsque vous annotez un SqlResultSetMapping dans une non-entité.

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

Ce n'est pas la manière suggérée. Le moyen le plus efficace est mentionné ci-dessus avec @SqlResultSetMapping, mais si vous voulez quelque chose de plus hardcore, vous pouvez accéder au résultat du gestionnaire d'entités par l'objet qu'il renvoie.

Par exemple :

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

Le fait de le faire avec q.getSingleResult(); ramène à u un objet de type Java.util.HashMap que vous pouvez utiliser pour accéder à vos résultats ligne par ligne.

Par exemple:

    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());
     }
0
AbstactVersion