2016-08-04 17 views
2

Wir haben ein paar Entitäten mit einer Reihe von Eigenschaften, die mit Hibernates @Formula Annotation versehen sind. Die SQL-Snippets in den Annotationen führen hauptsächlich skalare Unterabfragen durch (z. B. COUNT Abfragen). Als Beispiel haben wir eine 1: n-Beziehungshierarchie, die vier Ebenen tief ist: A <- B <- C <- D (wobei <- eine Eins-zu-viele-Verknüpfung markiert). Sehr oft möchten wir beim Abrufen einer Entität vom Typ A die Anzahl der verknüpften Entitäten vom Typ D wissen. Dafür verwenden wir eine @Formula -annotierte Eigenschaft in A.Lazy/Eager-Laden von @Formula-Spalten dynamisch steuern

Da wir diese Werte nicht jedes Mal benötigen, haben wir die @Formula Eigenschaften als lazy-loaded deklariert (wir haben die Bytecode-Erweiterung von Hibernate aktiviert, um dies zu ermöglichen). Bei einigen Abfragen möchten wir diese Eigenschaften gerne laden. Wir laden oft Hunderte von Entitäten vom Typ A in einer Abfrage, und es wäre leistungsmäßig wichtig, das Eager/Lazy-Laden dieser Eigenschaften dynamisch zu steuern. Wir verwenden bereits die Entity-Graphen von JPA, um zu steuern, welche Eigenschaften für bestimmte Abfragen geladen werden, aber Entity-Graphen scheinen hier nicht zu funktionieren. Selbst wenn wir die Eigenschaften @Formula im Entity-Diagramm auflisten, werden sie immer noch träge geladen.

Ist es möglich, das faule/eifrige Laden von @Formula Spalten dynamisch pro Abfrage zu steuern? Wir sind derzeit auf die JPA Criteria Query API beschränkt, und benannte Abfragen sind hier nicht möglich.

Update:

Die Eigenschaften in Frage sind nicht Vereinigungen zu anderen Einrichtungen, aber nur einige berechneten Werte. Dies bedeutet, dass z.B. Fetch-Profile gelten hier nicht, da sie nur auf Entity-Assoziationen anwendbar sind (oder zumindest habe ich die Hibernate manual verstanden). Hier ist ein Beispiel von einem unserer @Formula Eigenschaften:

@Entity 
public class A { 

    @Basic(fetch = FetchType.LAZY) 
    @Formula("(select count(*) from entity_D_table where ...)") 
    private int associatedDCount; 

    ... 
} 

Antwort

0

Sie können versuchen, einen Blick auf Hibernate Profile holen https://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html/ch20.html#performance-fetching-profiles zu haben.

können Sie zum Beispiel mit Anmerkungen versehen von einem Unternehmen wie die

@Entity 
@FetchProfile(name = "country_states", fetchOverrides = { 
      @FetchProfile.FetchOverride(entity = Country.class, association = "states", mode = FetchMode.JOIN) 
}) 
public class Country implements Serializable {... 

und aktivieren den Modus JOIN bei der Abfrage, wie folgt aus:

session=getSession(); 
session.beginTransaction(); 
//enable fetch profile for EAGER fetching 
session.enableFetchProfile("country_states"); 

Wie in http://www.concretepage.com/hibernate/fetchprofile_hibernate_annotation

+0

Aber sind die Abrufprofile nicht nur auf Entitätszuordnungen anwendbar? Ich habe ein Codebeispiel hinzugefügt, wie unsere Eigenschaften aussehen. Ich glaube nicht, dass die Abrufprofile hier funktionieren würden. –

+0

Sie haben Recht. Könnten Sie in Erwägung ziehen, eine SQL-Sicht in Ihrer DB zu definieren und eine neue Entität darauf abzubilden, um die Formel eifrig als einfache Eigenschaft zu holen? –

+0

Ich habe überlegt, eine Ansicht zu erstellen, aber das würde ziemlich viele Änderungen in der Codebasis erfordern. Momentan verwenden wir die JPA-Entity-Graphen, um Daten aus etwa einem Dutzend Tabellen auf einmal zu laden, und der Code erwartet, dass er das gesamte Entity-Diagramm erhält. Aber wenn der derzeitige Ansatz im Benchmarking zu langsam ist, müssen wir darüber erneut nachdenken. –

1

gezeigt Sie könnten die Verwendung Critria api, damit es anstelle einer Entität ein DTO zurückgibt.

Verwenden Sie in Ihrer Kriterienabfrage eine Projektion, um nur die Spalte auszuwählen, die Sie benötigen.

Auf diese Weise enthält die Select-Abfrage nur die Felder, die Sie fragen, unabhängig von der Zuordnung EAGER oder LAZY.

+0

Wir verwenden nicht die Kriterien-API von Hibernate, aber ich denke, dies ist auch mit der JPA Criteria Query API möglich. Dies würde einige Änderungen in unserer aktuellen Codebasis erfordern, könnte sich aber lohnen, wenn die aktuelle Implementierung als langsam angesehen wird. Löst nicht wirklich das unmittelbare Problem, sondern +1 für die Idee auf jeden Fall. –

+0

Aus meiner Erfahrung mit DTO anstelle von Entity ist viel besser für die Leistung, wenn ich nur Daten anzeigen müssen: Sie haben die Kontrolle über die Anzahl der Join oder Spalte und kann spezifische Index zu beschleunigen Abfragen noch mehr – jpprade

+0

Nun, die Die Anzahl der Joins kann mit den JPA-Entity-Graphen gesteuert werden, und ich bin der Ansicht, dass das Abrufen zu vieler Spalten nicht so groß sein sollte. Aber ja, die Verwendung von DTOs, wie Sie es beschreiben, ermöglicht mehr Kontrolle und Feinabstimmung. Zumindest in unserem Fall würde es aber auch mehr Implementierungsarbeit erfordern und die Komplexität des Codes erhöhen, und ich weiß nicht, ob das ein guter Kompromiss ist. –