ROUND(x, d) Long oder Integer statt Double! Liegt es an Hibernate?

ThirdKeeper

Mitglied
Hallo!

System:
MySQL 5.1.x, JBoss 4.2.3.GA, Hibernate

Problem:
Die folgende SQL Abfrage soll eine Liste mit den Typen Long und Double zurück geben, was auch im MySQL Query Browser funktioniert.
Code:
SELECT i.id, SUM(ROUND(item.aDoubleValue * item.aFloatValue, 2))
FROM ENTITY_ITEM item, ENTITY i
WHERE i.id = item.entity_Id
GROUP BY i.id

Führe ich nun die Abfrage im PersistenceContainer aus,
Code:
Query q = entityManager.createNamedQuery("ENTITY_SUM_ROUND_QUERY");
List <Object [ ]>values = q.getResultList();
wird die Liste mit den Typen Long, Long zurück gegeben.
Nehme ich nun den Round(x, d) raus, wird Long, Double zurückgegeben?
Nehme ich nun SUM(...) raus und lasse ROUND(...) in der Query, wird Long, Integer zurückgegeben?
Lt. MySQL Reference 5.1 gibt Round(x, d) ein Double Wert zurück.

Jemand eine Idee?
 
Hallo,

(nur mal so ne Vermutung...:) stimmen die Field-typen in deinen Hibernate Mappings mit denen in deinen POJOs überein? Sprich steht im Mapping long und am Pojo Attribut
auch?
Gruß Tom
 
Hab mir schon gedacht, dass so eine Frage kommt. :D
Nein es ist ein Double und ein Float Typ im Pojo. So liegen sie auch in der Datenbank (von Hibernate gemapped).

Wohlgemerkt der erste Typ soll ja Long sein, da es ein ID-Attribut ist. Nur der zweite Wert, der gerundet wird, muss Double sein.
Hier wird, wie im SELECT versucht aufzuzeigen, ein Double mit einem Float multipliziert.

Nehmen wir mal an, dass die beiden Attribute Long sind. Warum sollte durch das weglassen von SUM(...), dann Integer zurückgegeben werden?
Dann müssten die Werte wenn schon Integer sein, sonst würde es ja keinen Sinn machen. ;)

Es sind definitiv Werder Integer, noch Long Attribute des Pojos, die abgefragt werden. :confused:
 
Hallo,

ja es liegt an Hibernate - und an Dir ;), aber das ist eher ein philosophischer Standpunkt. Aber der Reihe nach.

Du benutzt den EntityManager und damit JPA. Ich gehe mal davon aus, dass das named query ein "normales" ist, sprich Du arbeitest auf Objekten und mit JPA-QL bzw. HQL. In JPA gibt es keine ROUND() Funktion. Die wird Dir bei Verwendung von Hibernate als Persistence Provider und dem entsprechenden (in Deinem Fall MySQL) Dialect aber trotzdem zur Verfügung gestellt.

Im MySQL Dialect ist ROUND aber mit einem festen Rückgabewert vom Typ Integer belegt. Das heißt er gibt auch nen Integer zurück, egal was die MySQL da im Hintergrund fabriziert. Damit sollte der Fall
Nehme ich nun SUM(...) raus und lasse ROUND(...) in der Query, wird Long, Integer zurückgegeben?
klar sein.

Die SUM() Funktion ist in JPA definiert, und liefert Long für alle ganzzahligen Werte und Double für alle Floatings sowie BigDecimal für BigDecimal und BigInteger für BigInteger zurück - (JPA Spec. 4.8.4). - was dann auch Deine restlichen Fälle erklärt.

wird die Liste mit den Typen Long, Long zurück gegeben.
Nehme ich nun den Round(x, d) raus, wird Long, Double zurückgegeben?
SUM(ROUND()) ist SUM() auf Integer, und gibt damit Long zurück. Und im zweiten Fall läuft SUM() auf einen nichtganzahligen Wert und gibt Double zurück.

Ich hoffe das war einigermassen verständlich.
Jemand eine Idee?
Entweder Du benutzt Spezialfunktionen wie round (die es ja nicht unbedingt in jeder DB gibt) nicht in normalen JPA-QL bzw. HQL Querries, oder Du bist dir halt der Einschränkungen bewusst. Als Alternative würde ich vorschlagen, Du benutzt einfach ein NamedNativeQuery - dann wird alles in der DB ausgeführt und sollte auch so funktionieren, wie Du es von normalen Abfragen gewohnt bist. Du musst dabei die Abfrage aber "nativ" formulieren - also keine Objektnamen etc. sondern Tabellen und Spaltennamen.

Du könntest natürlich auch den Dialect bzw. Hibernate erweitern ;)

Grüße
THMD
 
Danke THMD.

Super Antwort. Habe alles zu 100% verstanden. ;)
Das bringt mich ein ganzes Stück vorwärts. Nun kann ich eine gute Lösung realisieren.
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück