Map-Entity mit Abfrage in Hibernate
-
05-07-2019 - |
Frage
betrachtet Tabelle
sales (id, seller_id, amount, date)
und hier ist eine Ansicht, die von sales
mit Abfrage SELECT seller_id, SUM(amount) FROM sales GROUP BY seller_id
total_sales (seller_id, amount)
Ich möchte eine Einheit für einen Gesamtumsatz machen, aber ohne die Sicht auf die SQL-Seite.
Diese Einheit wird aus einer Abfrage erstellt werden. Das nächste, was ich gefunden ist this , aber ich konnte es nicht funktioniert.
Auch wenn ich den Loader definieren, Hibernate sucht nach der Tabelle des Unternehmens und gibt einen Fehler, wenn sie es nicht finden können. Wenn ich die Tabelle erstellen, ist es nicht die Einheit von der benannten Abfrage lädt I definiert, Hibernate generiert die Abfrage selbst.
Gibt es eine Möglichkeit @Loader zu machen, zu arbeiten oder gibt es eine andere Art und Weise, dass ich eine Anfrage an Unternehmen abbilden können?
Lösung
Warum gehst du nicht einfach new
in der Abfrage verwenden?
select new TotalSales(seller_id, count(seller_id))
from sales
group by seller_id
Sie haben soeben eine Klasse Totalsales mit einem Konstruktor schreiben die seller_id und eine ganze Zahl nehmen.
Bearbeiten : Wenn Kriterien API verwenden, können Sie die AliasToBeanResultTransformer
verwenden können (siehe API-Dokumentation ). Es kopiert all Alias-Name auf eine Eigenschaft mit dem gleichen Namen.
List list = s.createCriteria(Sales.class)
.setProjection(Projections.projectionList()
.add( Projections.property("id"), "SellerId" )
.add( Projections.rowCount("id"), "Count" ) )
.setResultTransformer(
new AliasToBeanResultTransformer(TotalSales.class) )
.list();
Dann wird Ihr TotalSales
braucht eine SellerId
und Count
Eigenschaft.
Andere Tipps
Neben Stefan Antwort, man könnte auch eine explizite HQL-Abfrage
verwenden SELECT seller_id, SUM(amount) FROM sales GROUP BY seller_id
Das Ergebnis ist natürlich in Liste gespeichert. Wenn dieser Datentyp für Sie ist nicht bequem, Sie konnte:
- Neue TotalSale Objekte mit ihnen (Verwendung Stefan Antwort wäre besser, wahrscheinlich)
- eine Karte erstellen, um die Daten zu speichern (Sie können auch diese einbetten können direkt in die Anfrage).
Sie können versuchen, eine angepasste Lader zu definieren. Früher habe ich das nie, aber es scheint vernünftig zu sein:
<sql-query name="totalSale">
<return alias="ts" class="TotalSale" />
SELECT seller_id as {ts.seller_id}, SUM(amount) as ts.amount
FROM sales
WHERE seller_id = ?
GROUP BY seller_id
</sql-query>
Nicht sicher, ob die Filter auf der seller_id benötigt wird.
Sie verweisen auf diese benannte Abfrage in einer Klassenzuordnung:
<class name="TotalSale">
<id name="seller_id">
<generator class="increment"/>
</id>
<property name="seller_id" />
<property name="amount" />
<loader query-ref="totalSale"/>
</class>
Es gibt mehr Details in das Handbuch .
Alternativ können Sie auch direkt eine Namensabfrage aus dem Code verwenden, auf diese Weise Sie nicht eine Abbildung von TotalSale brauchen und müssen nicht die Abfrage im Code schreiben. Benannte Abfragen können auch Objekte zurück. Siehe Details über benannten Abfragen in der Dokumentation.
Wenn Sie wirklich eine bestimmte Entität wollen nur für diesen Job Sie eine ‚Formel‘ auf einer benutzerdefinierten Eigenschaft verwenden können,
<class name="SellerSales" table="Sales" lazy="true">
<id name="SellerId" column="SellerId" type="int">
<generator class="native" />
</id>
<property name="SalesSum" type="float" update="false" insert="false"
formula="select SUM(sal.ammount) from sales sal where sal.seller_id = SellerId)" />
</class>
public class SellerSales
{
public int SellerId {get; set;}
public float SalesSum {get; set;}
}
als solche seine accesible der Kriterien Motor für auftrag durch die Beschränkungen usw., die ich denke, dass ist der Grund, warum Sie wollen, es zu benutzen.