Verwenden Sie weniger Spalten in SQL-Abfrage durch Hibernate Projektionen auf eine Entität mit ManyToOne Beziehung
-
06-07-2019 - |
Frage
Ich bin versucht, zu erstellen eine kleinere SQL, zu vermeiden "wählen Sie * aus," dass gebaut wird, standardmäßig für hibernate-Kriterien.
Wenn ich einfach Felder (keine Beziehung), die durch die "Transformers" habe ich verwalten können, um diese SQL:
select description, weight from Dog;
Hallo, ich habe diese Person:
@Entity
public class Dog
{
Long id;
String description;
Double weight;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "person_id", nullable = false)
Person owner;
}
@Entity
public class Person
{
Long id;
String name;
Double height;
Date birthDate;
}
Mein Ziel ist es dieses:
select description, weight, owner.name from Dog
Ich habe versucht, diese mit den Kriterien (und teilkriterien):
Criteria dogCriteria = sess.createCriteria(Dog.class);
ProjectionList proList = Projections.projectionList();
proList.add(Projections.property("description"), description);
proList.add(Projections.property("weight"), weigth);
dogCriteria.setProjection(proList);
Criteria personCriteria = dogCriteria.createCriteria("owner");
ProjectionList ownerProList = Projections.projectionList();
ownerProList.add(Projections.property("name"), description);
dogCriteria.setProjection(ownerProList); //After this line, debugger shows that the
//projection on dogCriteria gets overriden
//and the query fails, because "name" is
//not a field of Dog entity.
Wie soll ich-Projektionen, um eine kleinere SQL, weniger Spalten ?Vielen Dank im Voraus.
Lösung
Erste von alle,
select description, weight, owner.name from Dog
ist kein Gültiger SQL.Es müsste so etwas wie
select description, weight, Person.name
from Dog join Person on Dog.person_id = Person.id
statt.Zweitens, warum?Obwohl es möglich ist, das zu tun, was Sie möchten (siehe unten), es ist extrem ausführlich über die Kriterien-API und gewinnen Sie nichts zu zeigen für Sie.Einsparungen bei den Daten-transfer für ein paar Spalten sind vernachlässigbar, es sei denn, Spalten riesige blobs oder wählen Sie Hunderte oder Tausende von Datensätzen.In jedem Fall gibt es bessere Möglichkeiten, um mit diesem Problem umzugehen.
Anywho, das zu tun, was Sie wollen, für Kriterien, die Sie brauchen, um beizutreten verknüpften Tabelle (Person), per alias und geben Sie die Projektion auf main Kriterien mit Sprach alias:
Criteria criteria = session.createCriteria(Dog.class, "dog")
.createAlias("owner", "own")
.setProjection( Projections.projectionList()
.add(Projections.property("dog.description"))
.add(Projections.property("dog.weight"))
.add(Projections.property("own.name"))
);
Gibt es eine Beschreibung und ein Beispiel der oben genannten Kriterien Projektionen Dokumentation.Beachten Sie, dass, wenn es ausgeführt wird, die oben genannten Kriterien zurückkehren würde, eine Liste von Objekt-arrays.Sie müssen angeben ResultTransformer um die Ergebnisse haben konvertiert in realen Objekte.
Andere Tipps
Ich habe versucht, es noch nicht von mir, aber ich denke, Sie auch einen anderen Konstruktor in Ihrer Entity (Pojo) und die Spalten dort passieren können. Siehe https://www.thoughts-on-java.org/hibernate- best Practices / Kapitel "1.2 Pojo" für eine detaillierte Anleitung. Altough für mich ist es noch nicht klar, ob dies auch zu für ManyToOne Beziehungen funktioniert. Ich werde es versuchen.