Was ich habe:
@Entity
public class MyEntity {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@JoinColumn(name = "myentiy_id")
private List<Address> addreses;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@JoinColumn(name = "myentiy_id")
private List<Person> persons;
//....
}
public void handle() {
Session session = createNewSession();
MyEntity entity = (MyEntity) session.get(MyEntity.class, entityId);
proceed(session); // FLUSH, COMMIT, CLOSE session!
Utils.objectToJson(entity); //TROUBLES, because it can't convert to json lazy collections
}
Was für ein Problem:
Das Problem ist, dass ich nach Abschluss der Sitzung keine Lazy Collection mehr abrufen kann. Ich kann aber auch eine Sitzung in der Methode " Fortfahren" nicht schließen .
Was für eine Lösung (grobe Lösung):
a) Erzwingen Sie vor dem Schließen der Sitzung den Ruhezustand, um verzögerte Sammlungen abzurufen
entity.getAddresses().size();
entity.getPersons().size();
....
b) Vielleicht ist es elleganter, @Fetch(FetchMode.SUBSELECT)
Anmerkungen zu verwenden
Frage:
Was ist eine bewährte Methode / ein allgemeiner Weg / ein elleganterer Weg, dies zu tun? Bedeutet, mein Objekt in JSON zu konvertieren.
Sie können die Getters des Hibernate-Objekts in derselben Transaktion durchlaufen, um sicherzustellen, dass alle faulen untergeordneten Objekte mit der folgenden generischen Hilfsklasse eifrig abgerufen werden :
quelle
if (object instanceof List) { for(Object item : (List<Object>) object) { initializeObject(item, seenObjects, insidePackageName); } return; } else if (object instanceof Set) { for(Object item : (Set<Object>) object) { initializeObject(item, seenObjects, insidePackageName); } return; }
hinzugefügt : Iterieren Sie Listen, die sonst ignoriert werden.Nicht die beste Lösung, aber hier ist was ich habe:
1) Kommentieren Sie den Getter, den Sie mit dieser Annotation initialisieren möchten:
2) Verwenden Sie diese Methode (kann in eine generische Klasse eingefügt werden oder Sie können T mit der Objektklasse ändern) für ein Objekt, nachdem Sie es aus der Datenbank gelesen haben:
quelle
Platzieren Sie die Utils.objectToJson (Entität); Anruf vor dem Schließen der Sitzung.
Oder Sie können versuchen, den Abrufmodus einzustellen und mit Code wie diesem zu spielen
quelle
Mit Hibernate 4.1.6 wird eine neue Funktion eingeführt, um diese faulen Assoziationsprobleme zu lösen. Wenn Sie die Eigenschaft hibernate.enable_lazy_load_no_trans in hibernate.properties oder in hibernate.cfg.xml aktivieren, haben Sie keine LazyInitializationException mehr.
Weitere Informationen finden Sie unter: https://stackoverflow.com/a/11913404/286588
quelle
Wenn Sie mehrere Sammlungen abrufen müssen, müssen Sie:
Hibernate.initialize
für die verbleibenden Sammlungen.In Ihrem Fall benötigen Sie also eine erste JPQL-Abfrage wie diese:
Auf diese Weise können Sie Ihr Ziel mit 2 SQL-Abfragen erreichen und ein kartesisches Produkt vermeiden.
quelle
Hibernate#initialize(entity.getSubSet())
wenn getSubSet zurückkehrtCollections.unmodifyableSet(this.subSet)
. Ich habe es versucht und es nicht. Die zugrunde liegende Sammlung ist 'PersistentSet'. Gleiche Geschichte mit Anruf#size()
Es nähert sich wahrscheinlich nirgendwo einer Best Practice, aber ich rufe normalerweise eine
SIZE
in der Sammlung auf, um die Kinder in derselben Transaktion zu laden, wie Sie vorgeschlagen haben. Es ist sauber, immun gegen Änderungen in der Struktur der untergeordneten Elemente und liefert SQL mit geringem Overhead.quelle
Versuchen Sie es mit
Gson
Bibliothek, um Objekte in Json zu konvertierenBeispiel mit Servlets:
quelle
Wenn Sie das JPA-Repository verwenden, setzen Sie properties.put ("hibernate.enable_lazy_load_no_trans", true). zu jpaPropertymap
quelle
Du kannst den ... benutzen
@NamedEntityGraph
Anmerkung zu Ihrer Entität verwenden, um eine ladbare Abfrage zu erstellen, die festlegt, welche Sammlungen Sie in Ihre Abfrage laden möchten.Der Hauptvorteil dieser Auswahl besteht darin, dass der Ruhezustand eine einzige Abfrage zum Abrufen der Entität und ihrer Sammlungen ausführt, und zwar nur dann, wenn Sie dieses Diagramm wie folgt verwenden:
Entitätskonfiguration
Verwendung
quelle
Es gibt eine Art Missverständnis über faule Sammlungen in JPA-Hibernate. Lassen Sie uns zunächst klarstellen, warum der Versuch, eine faule Sammlung zu lesen, Ausnahmen auslöst und nicht einfach NULL für die Konvertierung oder weitere Anwendungsfälle zurückgibt..
Dies liegt daran, dass Nullfelder in Datenbanken, insbesondere in verbundenen Spalten, eine Bedeutung haben und nicht einfach den Status "Nicht dargestellt" haben, wie z. B. Programmiersprachen. Wenn Sie versuchen, eine Lazy-Sammlung als Nullwert zu interpretieren, bedeutet dies (auf der Datenspeicherseite), dass zwischen diesen Entitäten keine Beziehungen bestehen und dies nicht der Fall ist. Das Auslösen von Ausnahmen ist also eine Art Best Practice, und Sie müssen sich damit befassen, nicht mit dem Ruhezustand.
Wie oben erwähnt, empfehle ich:
Auch wie in anderen Antworten beschrieben, gibt es viele Ansätze (eifriges Abrufen, Beitreten usw.) oder Bibliotheken und Methoden, um dies zu tun, aber Sie müssen Ihre Sicht auf das Geschehen einrichten, bevor Sie sich mit dem Problem befassen und es lösen.
quelle