2012-08-07 1 views
17

Ich habe eine Hibernate Java Entität namens X verwaltet und eine native SQL-Funktion (myfunc), die ich von einer Hibernate SQL-Abfrage in dieser Richtung nennen:Wie kann man die Ergebnisse einer SQL-Abfrage am besten einem Nicht-Entity-Java-Objekt mit Hibernate zuordnen?

SQLQuery q = hibernateSession.createSQLQuery(
        "SELECT *, myfunc(:param) as result from X_table_name" 
      ); 

Was möchte ich tun, ist, das alles von zurück zur Karte Diese Abfrage an eine Klasse (nicht unbedingt von Hibernate verwaltet) namens Y. Y sollte alle Eigenschaften/Felder von X plus die result von myfunc, z Y könnte Klasse X erweitern und ein "Ergebnis" -Feld hinzufügen.

Was ich versucht habe:

  1. Ich habe versucht, mit q.addEntity(Y.class) aber irgendwie: org.hibernate.MappingException: Unknown entity com.mycompany.Y
  2. q.setResultTransformer(Transformers.aliasToBean(Y.class)); aber irgendwie: 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.
  3. q.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP); gibt eine Map zurück, aber die Werte sind nicht immer vom Typ, der vom entsprechenden Feld in X erwartet wird. Zum Beispiel können Felder in X vom Typ enum und Date nicht direkt von der von der SQL-Abfrage zurückgegebenen Map zugeordnet werden Saiten).

Was ist der richtige Weg, um mit dieser Situation umzugehen?

Antwort

15

Siehe die chapter of the documentation about SQL queries.

Sie können die Methode addScalar() verwenden, um anzugeben, welchen Typ Hibernat für eine bestimmte Spalte verwenden soll.

Und können Sie Aliasnamen verwenden, um die Ergebnisse mit den Bean-Eigenschaften zuzuordnen:

select t.some_property as someProperty, ..., myfunc(:param) as result from X_table_name t 

Oder (und obwohl es ein paar Zeilen Code erfordern, es ist meine bevorzugte Lösung), können Sie einfach tun, um die Zuordnung selbst :

List<Object[]> rows = query.list(); 
for (Object[] row : rows) { 
    Foo foo = new Foo((Long) row[0], (String) row[1], ...); 
} 

Dies vermeidet Reflexion und lässt Sie alles kontrollieren.

+2

Eek, eine Besetzung zu 'Long'. Woher weißt du im Voraus, dass 'row [0]' ein 'Long' sein wird? Gibt es eine Möglichkeit, die Datentypkonvertierung über die Hibernate-APIs zu erzwingen? –

+0

@LukasEder: Folgen Sie dem Link zur Dokumentation, dort wird erklärt. Aber die Verwendung von SQL-Abfragen mit Hibernate sollte extrem außergewöhnlich sein. In den meisten Fällen verwenden Sie HQL/Kriterien-Abfragen, und der Typ wird vom Typ des Feldes in Ihrer Entität abgeleitet. –

+0

Danke für die Info. Ich hätte deine Antwort vollständig lesen sollen ...Nichtsdestotrotz ist es immer noch ein bisschen schmerzhaft, dass die Typinformation wiederholt werden muss. –

0

Zunächst einmal müssen Sie die Einheit in der Hibernate XML-Konfigurationsdatei, so etwas erklären: ..... class = „Pfad zu Ihrem Unternehmen“

Oder Sie können programmatisch das gleiche tun vor Sie machen die Abfrage.

6

Einfach. Wirf die Zeilen auf Map<String, Object>:

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); 
} 
+0

Nette Idee, aber funktioniert nur, wenn Datenbankspalten genau wie die Entitätsfelder benannt werden. –

+0

Tolle Lösung .... Danke – sarwar026

Verwandte Themen