Ich habe eine im Ruhezustand verwaltete Java-Entität namens X und eine native SQL-Funktion (myfunc), die ich aus einer Hibernate-SQL-Abfrage heraus aufrufe:
SQLQuery q = hibernateSession.createSQLQuery(
"SELECT *, myfunc(:param) as result from X_table_name"
);
Ich möchte das Ergebnis dieser Abfrage einer Klasse zuordnen (die nicht unbedingt von Hibernate verwaltet wird) mit dem Namen Y. Y sollte alle Eigenschaften/Felder von X sowie die von result
zurückgegebene myfunc
enthalten, z. Y könnte die Klasse X erweitern und ein "Ergebnis" -Feld hinzufügen.
Was ich versucht habe:
q.addEntity(Y.class)
zu verwenden, aber dies schlägt fehl mit: org.hibernate.MappingException: Unknown entity com.mycompany.Y
q.setResultTransformer(Transformers.aliasToBean(Y.class));
aber dies schlägt fehl mit: org.hibernate.PropertyNotFoundException: Could not find setter for some_property
. X hat ein Feld namens someProperty
mit dem entsprechenden Getter und Setter, aber in diesem Fall scheint es nicht so, als würde Hibernate den Spaltennamen (some_property) dem richtigen Feldnamen zuordnen.q.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
gibt eine Map zurück, aber die Werte entsprechen nicht immer dem Typ, den das entsprechende Feld in X erwartet. Beispielsweise können Felder in X vom Typ enum und Date nicht direkt aus der Map zugeordnet werden, die von der SQL-Abfrage zurückgegeben wird (bei der es sich um Strings handelt).Wie kann man mit dieser Situation umgehen?
Siehe das Kapitel der Dokumentation zu SQL-Abfragen .
Mit der addScalar()
-Methode können Sie angeben, welchen Typ Hibernat für eine bestimmte Spalte verwenden soll.
Und Sie können Aliase verwenden, um die Ergebnisse mit den Bean-Eigenschaften abzubilden:
select t.some_property as someProperty, ..., myfunc(:param) as result from X_table_name t
Oder (und obwohl einige Codezeilen erforderlich sind, ist dies meine bevorzugte Lösung), können Sie die Zuordnung einfach selbst vornehmen:
List<Object[]> rows = query.list();
for (Object[] row : rows) {
Foo foo = new Foo((Long) row[0], (String) row[1], ...);
}
Dadurch werden Reflexionen vermieden und Sie können alles steuern.
Einfach. Die Zeilen in Map<String, Object>
umwandeln:
final org.hibernate.Query q = session.createSQLQuery(sql);
q.setParameter("geo", geo);
q.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
final List<Map<String, Object>> src = q.list();
final List<VideoEntry> results = new ArrayList<VideoEntry>(src.size());
for (final Map<String, Object> map:src) {
final VideoEntry entry = new VideoEntry();
BeanUtils.populate(entry, map);
results.add(entry);
}
Zunächst müssen Sie die Entität in der XML-Datei für den Ruhezustand der Konfiguration wie folgt deklarieren: ..... Class = "Pfad zu Ihrer Entität"
Oder Sie können dasselbe programmgesteuert ausführen, bevor Sie die Abfrage durchführen.