2016-04-18 3 views
0

Ich habe einen Namen nativen Abfrage:Wie ein zusätzliches Feld in einer benannten nativen Abfrage in dem Ruhezustand behandeln

@NamedNativeQueries({ 
    @NamedNativeQuery(
      name = "WeightLog.getAll", 
      query = "select weightLogId, dateOfLog, weight, weight - lag(weight) over (ORDER BY dateOfLog) as change, userId from weightLog order by dateOfLog desc", 
      resultClass = WeightLog.class)}) 

Wo ich „change“ zeigt die Differenz aus dem letzten Eintrag in dieser Spalte der Verzögerung Befehl .

Was ist der richtige Weg, dies in der Entität zu behandeln, so dass, wenn ich einen get bekomme ich es auf die Benutzeroberfläche zurückgeben kann, aber wenn ich ein create/update/delete es wird ignoriert werden?

Was ich getan habe es wie so kommentiert wird:

@Column(insertable = false, updateable=false) 
private Double change; 

Das bedeutet, dass während meiner getAll es wird im JSON zeigt von meinem REST-Endpunkt zurückgegeben werden und wird ignoriert, wenn ein/Update erstellen zu tun. Jedoch kann ich nicht von DB über den entsprechenden REST-Endpunkt löschen, da in delete-Methode in meinem DAO ich eine get verwende, die die "Änderung" zurückgibt.

Delete Methoden in DAO:

public WeightLog getById(final Long weightLogId){ 
    return get(weightLogId); 
} 

public Long deleteById(final Long weightLogId){ 
    final WeightLog weightLogToDelete = this.getById(weightLogId); 
    this.delete(weightLogToDelete); 
    return weightLogToDelete.getWeightLogId(); 
} 

private void delete(final WeightLog weightLog){ 
    currentSession().delete(weightLog); 
} 

Ausnahme ist:

ERROR [2016.04.18 21: 06: 32.365] io.dropwizard.jersey.errors.LoggingExceptionMapper: Fehler ein Anforderungshandhabungs : 1f50d70af5fc5606 ! org.postgresql.util.PSQLException: FEHLER: spalte weightlog0_.change existiert nicht ! Position: 51

@Transient ist nicht gut und es scheint, dass dies in beide Richtungen dann ignoriert wird und für keine der CRUD-Operationen angezeigt wird.

Ich vermute, dass das, was ich oben habe, völlig die falsche Art ist, dies zu tun und ist nur ein "hacky" Weg, so weit wie ich zu bekommen so fühlen Sie sich frei, mir zu sagen, was ich getan habe, ist völlig falsch und zeigen Sie mir in der richtigen Richtung, wie mit diesem Fall der Verwendung von Verzögerung umzugehen ist. Ich würde es vorziehen, wenn möglich Anmerkungen zu verwenden.

EDIT FÜR OPTION EINS:

Nach der ersten Option von Dimitri unten, wie die json Daten an die UI zurückgegeben wird, ist dieses Format:

[ 
{ 
    "weightLogId": 15, 
    "dateOfLog": "2016-04-30", 
    "weight": 55, 
    "userId": 1 
}, 
-31.7] 

Mit dem Wechsel auf seine eigene mit kein Name angehängt. Dies macht es schwierig, dieses Attribut tatsächlich auf den Bildschirm no gedruckt zu bekommen? Ich verwende Backbone am Frontend, um model.attribute oder model.get ('attribte') nicht aufrufen zu können. Mit meinem alten kalt das Format etwas wie gewesen wäre:

{ 
    "weightLogId": 5, 
    "dateOfLog": "2016-03-13", 
    "weight": 87.5, 
    "userId": 1, 
    "change": 0 
} 

Auf jeden Fall kann ich den „Namen“ in der ResultSetMapping hier zeigen aufgegeben werden?

Sein vermasselt tatsächlich das JSON-Format vollständig wie nun die Attribute in einem Objekt um eine Ebene sind nach unten und jetzt nicht mit dem Backbone-Modell-Format auf dem Benutzeroberfläche zusammenpassen, das ist:

defaults: { 
     weight: 0, 
     dateOfLog: "2016-01-01", 
     userId: 1, 
     change: "0" 
    }, 

Als Referenz der ResultMapping wurde eingesetzt:

@SqlResultSetMapping(
    name = "WeightLogWithChange", 
    entities = { 
      @EntityResult(
        entityClass = WeightLog.class, 
        fields = { 
          @FieldResult(name = "weightLogId", column = "weightLogId"), 
          @FieldResult(name = "userId", column = "userId"), 
          @FieldResult(name = "dateOfLog", column = "dateOfLog"), 
          @FieldResult(name = "weight", column = "weight") 
        }), 
    }, 
    columns = @ColumnResult(name = "change", type = Double.class) 

)

Einfüg.Nummer OPTION 2

Für Option zwei wie würde die genannte Abfrage ändern?

@NamedNativeQueries({ 
    @NamedNativeQuery(
      name = "WeightLog.getAll", 
      query = "select weightLogId, dateOfLog, weight, weight - lag(weight) over (ORDER BY dateOfLog) as change, userId from weightLog order by dateOfLog desc", 
      resultSetMapping = "WeightLogWithChange" 
    ) 

})

Hier enthält die Verzögerung SQL. Wenn dieser Lag-Teil in eine Formel über dem Attribut verschoben wird, wie ändert sich dann diese benannte Abfrage? Ich nehme an, dass der Lag-Teil hier entfernt werden muss?

Antwort

2

Wenn ich richtig verstanden habe, möchte das change Attribut sichtbar sein, wenn die Abfrage ausgeführt wird, aber unsichtbar in löschen/aktualisieren/einfügen Operationen.

Lösung 1

Eine Möglichkeit ist, diesen Parameter separat und nicht als Entitätsattribut zu behandeln, aber es immer noch an der Einheit der Nähe hält eine JPA Funktion, die @SqlResultSetMapping (documentation) verwendet.

Ihre Unternehmen wie dies mit der neuen Mapping-Annotation aussehen werden (alle andere Anmerkungen zu ignorieren):

@SqlResultSetMapping(
    name = "WeightLogWithChange", 
    entityClass = WeightLog.class, 
    fields = { 
     @FieldResult(name = "id", column = "weightLogId"), 
     @FieldResult(name = "userId", column = "userId"), 
     @FieldResult(name = "someDate", column = "dateOfLog"), 
     @FieldResult(name = "weight", column = "weight")}), 
    columns = @ColumnResult(name = "change", type = Double.class)) 
class WeightLog { 
    //.. 
} 

Der Aufruf der Mutter Abfrage wäre dann:

EntityManager em = emf.createEntityManager(); 
em.getTransaction().begin(); 

List<Object[]> results = em.createNativeQuery("select weightLogId, dateOfLog, weight, weight - lag(weight) over (ORDER BY dateOfLog) as change, userId from weightLog order by dateOfLog desc", "WeightLogWithChange").getResultList(); 

results.stream().forEach((result) -> { 
    log.info("This is my weightLog object:" + result[0] + " and this is my computed change stored in a separate var: " + result[1]); 
}); 

em.getTransaction().commit(); 
em.close(); 

Hinweis in den obigen Beispiel: 1) wie wir die zurückgegebenen Spaltenwerte der SQL Entitätsattribute und die change Variable einem bestimmten Typ zuordnen und 2) wie wir das Ergebnis der systemeigenen Abfrage als Array erhalten, wobei das erste Element die zurückgegebene Entität ist objec t und Sekunde die Variable change wir kartiert.

Lösung 2

Sie konnten die change innerhalb des Unternehmens halten und es als Formel markieren, die eine Hibernate Spezifikum.

Vom documentation:

A powerful feature is derived properties. These properties are by definition read-only. The property value is computed at load time. You declare the computation as an SQL expression. This then translates to a SELECT clause subquery in the SQL query that loads an instance.

In diesem Fall kann das Attribut wie folgt aussehen würde:

//you have to check the validity of the SQL 
@Formula("(select weight - lag(weight) over (ORDER BY dateOfLog) from weightLog wl where wl.id = id)") 
private Double change; 
+0

Hallo Dimitri, danke für die Antwort. Ich habe deine erste Option ausprobiert, das funktioniert aber jetzt sind meine JSON-Daten, die auf die Benutzeroberfläche zurückgegeben werden, nicht in einem guten Format. Ill aktualisieren Sie die Frage mit den Details. – caseballs

+0

@caseballs Wenn Sie diese Antwort hilfreich finden, können Sie sie aktualisieren und/oder akzeptieren. In Bezug auf die JSON-Frage - es ist nicht direkt mit dem Winterschlaf verbunden, oder? Es kann sehr wohl eine separate Frage sein, die sich nur auf diesen Aspekt konzentriert. – dimitrisli

+0

Ich habe es als Antwort akzeptiert, aber kann nicht upvote, da ich nicht genug Ruf habe. Ich denke, der JSON-Teil von diesem ist gültig, ich möchte nicht etwas auf der Benutzeroberfläche hacken müssen, um die Attribute zu bekommen (was ich könnte, wie sie verfügbar sind), ich möchte lernen, wie man das richtig macht, so dass Die Abfrage wird in einem Format zurückgegeben, das dann im richtigen Format an die Benutzeroberfläche zurückgegeben werden kann. Angesichts der Tatsache, dass die alte Abfrage (mit ihren Problemen) in der Lage war, das richtige Format zurückzugeben, denke ich, dass es eine Möglichkeit geben muss, diese neue "Abfrage" mit ResultMapping durchzuführen, um auch das korrekte Format zurückzugeben. – caseballs

Verwandte Themen