web-dev-qa-db-fra.com

Spring Data JPA: Comment Query peut-il renvoyer des objets non-entités ou une liste d'objets?

J'utilise les données de printemps JPA dans mon projet. Je joue avec des millions de disques. J'ai une exigence où je dois récupérer des données pour différentes tables et construire un objet puis le peindre sur une interface utilisateur. Maintenant, comment y parvenir mes référentiels de données Spring. J'ai lu que cela peut être réalisé par des requêtes natives nommées.

Si la requête native nommée ne renvoie pas d'entité ou de liste d'entités, nous pouvons mapper le résultat de la requête sur un type de retour correct en utilisant l'annotation @SqlResultSetMapping.

Mais quand j'essaie d'utiliser @SqlResultSetMapping il en faut un autre entityResult. Ce que je comprends, c'est qu'il s'agit simplement de transformer un résultat de requête en ensemble de résultats d'entité uniquement, mais je veux un ensemble de résultats d'objets non-entités.

@SqlResultSetMapping(
    name="studentPercentile",
    entities={
        @EntityResult(
           entityClass=CustomStudent.class,
              fields={
                  @FieldResult(name="id", column="ID"),
                  @FieldResult(name="firstName", column="FIRST_NAME"),
                   @FieldResult(name="lastName", column="LAST_NAME")
              }         
        )
   }
) 
@NamedNativeQuery(
    name="findStudentPercentile", 
    query="SELECT * FROM STUDENT", 
    resultSetMapping="studentPercentile")

Dans l'exemple ci-dessus, j'essaie simplement d'obtenir les résultats de l'entité étudiante dans un autre pojo 'CustomStudent' qui n'est pas une entité. ( Cet exemple que j'essaie d'exécuter juste à des fins de POC, la cas d'utilisation réelle est beaucoup plus compliquée, avec une requête compliquée renvoyant des résultats différents ).

Comment réaliser au-dessus du cas d'utilisation? Existe-t-il un autre moyen que d'utiliser la requête de nom que ma méthode de référentiel renvoie des objets non-entités?

33
DHRUV BANSAL

J'ai été profondément surpris lorsque je suis tombé sur cela pour la première fois mais, oui, vous pouvez mapper les résultats de requête en utilisant @SqlResultSetMapping uniquement aux scalaires et aux entités gérées.

Le mieux que vous puissiez faire, je suppose, est d'ignorer le mappage automatique. Une requête sans mappage retournerait List<Object[]> et vous pouvez le mapper comme vous le souhaitez.

Une autre approche serait d'utiliser @MappedSuperclass. La classe désignée comme @MappedSuperclass (CustomStudent dans votre cas) peut être (pas sûre à 100%, cependant) dans @SqlResultSetMapping. mais vous devez introduire une hiérarchie d'héritage, c'est-à-dire que votre entité Student doit étendre CustomStudent. Cela aspirerait la plupart du temps de la bonne conception OO, car l'héritage serait un peu artificiel ...

24

Vous pouvez faire quelque chose comme

@NamedQuery(name="findWhatever", query="SELECT new path.to.dto.MyDto(e.id, e.otherProperty) FROM Student e WHERE e.id = ?1")

Ensuite, l'objet MyDto aurait juste besoin d'un constructeur défini avec les champs corrects, c'est-à-dire.

public MyDto(String id, String otherProperty) { this.id = id; this.otherProperty = otherProperty; }
24
tlavarea

Que diriez-vous de JPA 2.1 ConstructorResult ?

@SqlResultSetMapping(
    name="studentPercentile",
    classes={
        @ConstructorResult(
            targetClass=CustomStudent.class,
            columns={
                @ColumnResult(name="ID"),
                @ColumnResult(name="FIRST_NAME"),
                @ColumnResult(name="LAST_NAME")
            }
        )
    }
)

@NamedNativeQuery(name="findStudentPercentile", query="SELECT * FROM STUDENT", resultSetMapping="studentPercentile")
18
Daimon