/ / Die Initialisierung der Lazy-Sammlung schlägt im Hibernate fehl - Java, Hibernate, Collections, Lazy-Initialisierung

Die Initialisierung der Lazy-Sammlung schlägt im Ruhezustand fehl - Java, Hibernate, Collections, Lazy-Initialisierung

Heute habe ich mit dem nächsten Problem im Winterschlaf konfrontiert:

Meine Methode:

@Transactional
public Period getDefault(Team team) {
Period defaultPeriod = team.getDefaultPeriod();
List<Period> periods = _periodDAO.getPeriods(team);
if (!periods.contains(defaultPeriod)) {
defaultPeriod = periods.get(periods.size() - 1);
}
}
_periodDAO.initializeIssues(defaultPeriod);
return defaultPeriod;
}

Methode initializeIssues:

public void initializeIssues(Period period) {
if (period.getIssues() != null) {
Hibernate.initialize(period.getIssues());
}
}

Ich erhalte eine Ausnahme bei der Sammlung Perioden enthält defaultPeriod

Caused by: org.hibernate.HibernateException: collection is not associated with any session
at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:474)
at org.hibernate.Hibernate.initialize(Hibernate.java:417)

Aber wenn ich einige Zeilen entfernen und Methode zu ändern

@Transactional
public Period getDefault(Team team) {
Period defaultPeriod = team.getDefaultPeriod();
_periodDAO.initializeIssues(defaultPeriod);
return defaultPeriod;
}

Es funktioniert gut.

Ich debuggte zuerst Beispiel und Hibernate-Sitzung wird während der gesamten Methode nicht geschlossen.

Wie ich verstehe, wenn geladenes Objekt (ein Element in Perioden) in der Sitzung hat Sammlung, die aktive Sitzung zugeordnet und vor Objekt (defaultPeriod) hat auch die gleiche Assoziation - es (defaultPeriod) wird seine Assoziation verlieren.

Ist es wahr? Wer hat noch das gleiche Problem?

Danke für die Antworten.

Antworten:

13 für die Antwort № 1

Vermutlich, dein Team Argument kommt von einer anderen Transaktion und einem anderen Hibernate Session.

Wenn ein @Transactional Methode gibt zurück, die TransactionManager schließt die Session was macht einige Aufräumarbeiten und Unsets (setzt auf null) das Session Feld von allen PersistentCollection Instanzen. Ihre defaultPeriod hat eine von diesen in seiner issues Feld.

Hibernate "s Hibernate.initialize() Erzwingt die Initialisierung eines Lazy PersistentCollection, aber hat den folgenden Code (Anrufe AbstractPersistentCollection#forceInitialization())

    if ( session == null ) {
throw new HibernateException( "collection is not associated with any session" );
}

Wenn Sie planen, die issues Sammlung außerhalb des Originals @Transactional Methode (der Code, der produziert Team), müssen Sie die zugrunde liegenden Objekte laden. Entweder ändern Sie es in EAGER laden oder tun Sie, was Sie tun Hibernate.initialize().

Eine andere Lösung ist die Session dauern länger als nur die Länge des ersten @Transactional, aber ich habe keine Details dafür. Eine schnelle Google oder SO Suche sollte einige Optionen aufzeigen.


Das ist was passiert

Period defaultPeriod = team.getDefaultPeriod();

bekommt ein Period Objekt mit ID (zB) 42. Weil es in einem anderen passiert ist Session das ist seitdem geschlossen worden, der issues ist ein PersistentCollection was hat a null Session Referenz und wird die werfen Exception du erhältst.

Das machst du

List<Period> periods = _periodDAO.getPeriods(team);

Lassen Sie uns das sagen List enthält ein Period Objekt mit ID 42so if im

   if (!periods.contains(defaultPeriod)) {
defaultPeriod = periods.get(periods.size() - 1);
}

wird nicht ausgeführt. Obwohl die equals() kehrt zurück true (contains() kommt auch zurück true und wird false durch !), die Objekte sind nicht gleich. Das in der List hat einen Anhang (nicht null) Session, damit man initialisiert werden kann. Aber deine, die, die du hältst defaultPeriod kann nicht.