Ich bin ein Neuling im Ruhezustand und schreibe eine einfache Methode, um eine Liste von Objekten zurückzugeben, die einem bestimmten Filter entsprechen. List<Foo>
schien ein natürlicher Rückgabetyp zu sein.
Was auch immer ich tue, ich kann den Compiler nicht glücklich machen, es sei denn, ich beschäftige einen hässlichen @SuppressWarnings
.
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
public class Foo {
public Session acquireSession() {
// All DB opening, connection etc. removed,
// since the problem is in compilation, not at runtime.
return null;
}
@SuppressWarnings("unchecked") /* <----- */
public List<Foo> activeObjects() {
Session s = acquireSession();
Query q = s.createQuery("from foo where active");
return (List<Foo>) q.list();
}
}
Das würde ich gerne loswerdenSuppressWarnings
. Aber wenn ich das tue, bekomme ich die Warnung
Warning: Unchecked cast from List to List<Foo>
(Ich kann es ignorieren, aber ich möchte es gar nicht erst bekommen), und wenn ich das Generikum entferne, um es dem .list()
Rückgabetyp anzupassen , erhalte ich die Warnung
Warning: List is a raw type. References to generic type List<E>
should be parameterized.
Ich bemerkte , dass org.hibernate.mapping
tut ein erklären List
; aber es ist insgesamt ein anderer Typ - Query
gibt a java.util.List
als Rohtyp zurück. Ich finde es seltsam, dass ein neuerer Ruhezustand (4.0.x) keine parametrisierten Typen implementiert, daher vermute ich, dass ich stattdessen etwas falsch mache.
Es sieht dem Ergebnis von Cast Hibernate für eine Liste von Objekten sehr ähnlich , aber hier habe ich keine "harten" Fehler (das System kennt den Typ Foo und ich verwende keine SQLQuery, sondern eine direkte Abfrage). Also keine Freude.
Ich habe auch betrachtet Hibernate Class Cast Exception , da es viel versprechend aussah, aber dann merkte ich , dass ich nicht wirklich bekommen jede Exception
... mein Problem ist nur , dass eine Warnung - eine Codierung Stil, wenn man so will.
Die Dokumentation auf jboss.org, Hibernate-Handbücher und einige Tutorials scheinen das Thema nicht so detailliert zu behandeln (oder ich habe nicht an den richtigen Stellen gesucht?). Wenn sie ins Detail gehen, verwenden sie On-the-Fly-Casting - und dies in Tutorials, die nicht auf der offiziellen jboss.org-Website waren, also bin ich etwas vorsichtig.
Der einmal kompilierte Code läuft ohne offensichtliche Probleme ... von denen ich weiß ... bis jetzt; und die Ergebnisse sind die erwarteten.
Also: mache ich das richtig? Vermisse ich etwas Offensichtliches? Gibt es einen "offiziellen" oder "empfohlenen" Weg, dies zu tun ?
final
Class<?>
inlist()
, kann das Problem gelöst werden. Es ist eine Schande, solch eine hässliche API zu verwenden.List<Object>
. Die Ergebnisse sollten in den erwarteten Typ umgewandelt und Komponententests hinzugefügt werden, um sicherzustellen, dass die Abfrage die richtigen Ergebnisse zurückgibt. Es ist nicht akzeptabel, dass Fehler bei Abfragen " später im Code " auftreten. Ihr Beispiel ist ein Argument gegen Kodierungspraktiken, die im 21. Jahrhundert ein Gräuel sein sollten. Es ist, würde ich vorschlagen, niemals akzeptabel, eine zu habenList<Object>
.Die Lösung besteht darin, stattdessen TypedQuery zu verwenden. Wenn Sie eine Abfrage aus dem EntityManager erstellen, rufen Sie sie stattdessen folgendermaßen auf:
Dies funktioniert auch für benannte Abfragen, native benannte Abfragen usw. Die entsprechenden Methoden haben dieselben Namen wie diejenigen, die die Vanille-Abfrage zurückgeben würden. Verwenden Sie dies einfach anstelle einer Abfrage, wenn Sie den Rückgabetyp kennen.
quelle
Sie können Compiler-Warnungen mit folgenden Problemumgehungen vermeiden:
Es gibt jedoch einige Probleme mit diesem Code:
Und der Unterschied ist nur kosmetischer Natur, daher ist die Verwendung solcher Problemumgehungen meiner Meinung nach sinnlos.
Sie müssen mit diesen Warnungen leben oder sie unterdrücken.
quelle
Um Ihre Frage zu beantworten, gibt es keinen "richtigen Weg", dies zu tun. Wenn Sie nur von der Warnung gestört werden, können Sie die Verbreitung am besten vermeiden, indem Sie die
Query.list()
Methode in ein DAO einbinden:Auf diese Weise können Sie die
@SuppressWarnings("unchecked")
nur einmal verwenden.quelle
Die einzige Möglichkeit für mich war die Arbeit mit einem Iterator.
Mit anderen Methoden, die ich fand, hatte ich Casting-Probleme
quelle
Destinstion
für Sie bauen kann, oder? Verwenden derselect new
Syntax. Dies ist sicherlich nicht der richtige Ansatz.quelle
Sie verwenden einen ResultTransformer wie folgt:
quelle
q
ist immer noch einQuery
und ist daherq.list()
immer noch ein roherjava.util.List
Typ. Die Besetzung ist dann noch deaktiviert; Eine interne Änderung des Objekttyps sollte nichts nützen ...from foo where active
ist keine native Abfrage. Es ist also kein Ergebnis-Transformator erforderlich, da die Standardzuordnung ausreicht. Bei der Frage geht es nicht um das Umwandeln der POJO-Felder, sondern um das Umwandeln des Ergebnisobjekts. Ein Ergebnis-Transformator würde hier nicht helfen.Der richtige Weg ist die Verwendung von Transformatoren im Ruhezustand:
.
Das Durchlaufen von Object [] ist redundant und hätte einige Leistungseinbußen zur Folge. Detaillierte Informationen zur Verwendung von Transofrmern finden Sie hier: Transformers für HQL und SQL
Wenn Sie nach einer noch einfacheren Lösung suchen, können Sie einen sofort einsatzbereiten Kartentransformator verwenden:
quelle
Query
Ergebnissen - was in Ihrem Beispiel immer noch benötigt wird. Und Ihr Beispiel hat nichts mit dem Original zu tunfrom foo where active
.Nur Transformers verwenden Es hat bei mir nicht funktioniert. Ich habe eine Ausnahme vom Typ Cast erhalten.
sqlQuery.setResultTransformer(Transformers.aliasToBean(MYEngityName.class))
hat nicht funktioniert, weil ich Array of Object im Rückgabelistenelement erhalten habe, nicht den festen MYEngityName-Typ des Listenelements.Es hat bei mir funktioniert, wenn ich folgende Änderungen vornehme. Wenn ich
sqlQuery.addScalar(-)
jede ausgewählte Spalte und ihren Typ hinzugefügt habe und für eine bestimmte Spalte vom Typ String den Typ nicht zuordnen muss. mögenaddScalar("langCode");
Und ich habe MYEngityName mit NextEnity verbunden. Wir können nicht nur
select *
in der Abfrage ein Array von Objekten in der Rückgabeliste angeben .Unten Codebeispiel:
Es könnte jemandem helfen. auf diese Weise für mich arbeiten.
quelle
Ich habe hier die beste Lösung gefunden . Der Schlüssel zu diesem Problem ist die addEntity- Methode
quelle