2013-05-07 8 views
31

Ich verwende Federdaten JPA in meinem Projekt. Ich spiele mit Millionen von Platten. Ich habe eine Anforderung, wo ich Daten für verschiedene Tabellen abrufen und ein Objekt erstellen und dann auf einer Benutzeroberfläche malen muss. Nun, wie Sie dies erreichen, meine Spring Data Repositories. Ich habe gelesen, dass es durch benannte native Abfragen erreicht werden kann.Spring Data JPA: Wie kann die Abfrage Objekte oder eine Liste von Objekten zurückgeben?

Wenn die benannte nativen Abfrage keine Einheit oder eine Liste von Einheiten zurückkehren, können wir das Abfrageergebnis auf einen korrekten Rückgabetyp von mit dem @SqlResultSetMapping kommentierten Abbildung.

Aber wenn ich versuche, @SqlResultSetMapping zu verwenden, um es macht einen weiteren entityResult. Was ich verstehe, ist, dass es nur eine Transformation eines Abfrageergebnisses in Entity - Ergebnismenge ist, aber ich möchte eine Ergebnismenge von Nicht - Entitäts - Objekten.

@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") 

In obigem Beispiel versuche ich nur ein Ergebnis von Student Entity in einer anderen pojo zu bekommen ‚CustomStudent‘, der kein Unternehmen ist. (Dieses Beispiel, das ich versuche, nur für POC-Zweck auszuführen, ist tatsächlicher Usecase viel komplizierter, mit komplizierter Abfrage, die unterschiedliche resultset zurückgibt).

Wie erreicht man obigen Anwendungsfall? Gibt es einen anderen Weg neben der Verwendung der Namensabfrage, dass meine Repository - Methode Nicht - Entitäten - Objekte zurückgibt?

+0

Ich stieß vor kurzem auf das gleiche Problem und freue mich, jemanden zu sehen und eine Lösung dafür zu bekommen! –

Antwort

23

Ich war zutiefst überrascht, als ich das zum ersten Mal sah, aber ja, Sie können Abfrageergebnisse mit @SqlResultSetMapping nur auf Skalare und verwaltete Entitäten abbilden.

Das Beste, was Sie tun können, ist, denke ich, ist das automatische Mapping überspringen. Abfrage ohne Zuordnung würde List<Object[]> zurückgeben und Sie können es wie gewünscht zuordnen.

Ein anderer Ansatz wäre die Verwendung von @MappedSuperclass. Die als @MappedSuperclass (in Ihrem Fall CustomStudent) bezeichnete Klasse kann (nicht sicher 100%) in @SqlResultSetMapping verwendet werden. Sie müssen jedoch die Vererbungshierarchie einführen, dh Ihre Student-Entität muss CustomStudent erweitern. Das würde die meiste Zeit von der richtigen OO-Design saugen, weil Vererbung ein wenig künstlich sein würde ...

+0

Meinst du Primitive Typen? – Alex78191

+1

Sie können ConstructorResult verwenden https://Stackoverflow.com/a/42942353/4854931 – Alex78191

21

können Sie etwas tun, wie

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

Dann würde das MyDto Objekt nur ein Konstruktor definiert brauchen mit den richtigen Feldern dh

public MyDto(String id, String otherProperty) { this.id = id; this.otherProperty = otherProperty; } 
+0

kann ich etwas wie 'SELECT neuen Pfad.zu.dto.MyDto (e.id, neuer Pfad.zu.dto.OtherDto)' – masSdev

+0

schreiben Nein, aber in Ihrem MyDto könnten Sie eine OtherDto-Eigenschaft haben und im Konstruktor von MyDto könnten Sie die OtherDto-Eigenschaft mit den Daten setzen, die an den MyDto-Konstruktor übergeben wurden. Oder Sie könnten die Annotation @SqlResultSetMapping verwenden. – tlavarea

+0

Wenn ich dies schreibe, schlägt die Kompilierung mit 'Validierung fehlgeschlagen für die Abfrage für die Methode public abstract..' fehl. –

17

Wie wäre es 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") 
+0

Hallo, das hört sich gut an, aber NamedQuery muss noch angehängt werden und Entity muss Teil der Persistenzeinheit sein? – romainbsl

Verwandte Themen