Ich bekomme folgende Ausnahme:
Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at sei.persistence.wf.entities.Element_$$_jvstc68_47.getNote(Element_$$_jvstc68_47.java)
at JSON_to_XML.createBpmnRepresantation(JSON_to_XML.java:139)
at JSON_to_XML.main(JSON_to_XML.java:84)
wenn ich versuche, von main die folgenden Zeilen anzurufen:
Model subProcessModel = getModelByModelGroup(1112);
System.out.println(subProcessModel.getElement().getNote());
Ich habe die getModelByModelGroup(int modelgroupid)
Methode zunächst folgendermaßen implementiert :
public static Model getModelByModelGroup(int modelGroupId, boolean openTransaction) {
Session session = SessionFactoryHelper.getSessionFactory().getCurrentSession();
Transaction tx = null;
if (openTransaction) {
tx = session.getTransaction();
}
String responseMessage = "";
try {
if (openTransaction) {
tx.begin();
}
Query query = session.createQuery("from Model where modelGroup.id = :modelGroupId");
query.setParameter("modelGroupId", modelGroupId);
List<Model> modelList = (List<Model>)query.list();
Model model = null;
for (Model m : modelList) {
if (m.getModelType().getId() == 3) {
model = m;
break;
}
}
if (model == null) {
Object[] arrModels = modelList.toArray();
if (arrModels.length == 0) {
throw new Exception("Non esiste ");
}
model = (Model)arrModels[0];
}
if (openTransaction) {
tx.commit();
}
return model;
} catch(Exception ex) {
if (openTransaction) {
tx.rollback();
}
ex.printStackTrace();
if (responseMessage.compareTo("") == 0) {
responseMessage = "Error" + ex.getMessage();
}
return null;
}
}
und bekam die Ausnahme. Dann schlug mir ein Freund vor, die Sitzung immer zu testen und die aktuelle Sitzung abzurufen, um diesen Fehler zu vermeiden. Also habe ich das gemacht:
public static Model getModelByModelGroup(int modelGroupId) {
Session session = null;
boolean openSession = session == null;
Transaction tx = null;
if (openSession) {
session = SessionFactoryHelper.getSessionFactory().getCurrentSession();
tx = session.getTransaction();
}
String responseMessage = "";
try {
if (openSession) {
tx.begin();
}
Query query = session.createQuery("from Model where modelGroup.id = :modelGroupId");
query.setParameter("modelGroupId", modelGroupId);
List<Model> modelList = (List<Model>)query.list();
Model model = null;
for (Model m : modelList) {
if (m.getModelType().getId() == 3) {
model = m;
break;
}
}
if (model == null) {
Object[] arrModels = modelList.toArray();
if (arrModels.length == 0) {
throw new RuntimeException("Non esiste");
}
model = (Model)arrModels[0];
if (openSession) {
tx.commit();
}
return model;
} catch(RuntimeException ex) {
if (openSession) {
tx.rollback();
}
ex.printStackTrace();
if (responseMessage.compareTo("") == 0) {
responseMessage = "Error" + ex.getMessage();
}
return null;
}
}
}
aber trotzdem den gleichen Fehler bekommen. Ich habe viel für diesen Fehler gelesen und einige mögliche Lösungen gefunden. Eine davon war, lazyLoad auf false zu setzen, aber ich darf das nicht. Deshalb wurde mir vorgeschlagen, die Sitzung zu steuern
Wenn Sie Spring verwenden, markieren Sie die Klasse als @Transactional , dann übernimmt Spring die Sitzungsverwaltung.
Durch die Verwendung
@Transactional
werden viele wichtige Aspekte wie die Transaktionsweitergabe automatisch behandelt. In diesem Fall hat die Methode die Möglichkeit, sich der laufenden Transaktion anzuschließen, wenn eine andere Transaktionsmethode aufgerufen wird, wobei die Ausnahme "Keine Sitzung" vermieden wird.WARNUNG Wenn Sie verwenden
@Transactional
, beachten Sie bitte das resultierende Verhalten. In diesem Artikel finden Sie häufige Fallstricke. Beispielsweise bleiben Aktualisierungen von Entitäten erhalten, auch wenn Sie nicht explizit aufrufensave
quelle
@EnableTransactionManagement
Ihrer Konfiguration etwas hinzufügen müssen, um Transaktionen zu aktivieren. " Wenn eine andere Transaktionsmethode aufgerufen wird, hat die Methode die Möglichkeit, sich der laufenden Transaktion anzuschließen. " Dieses Verhalten unterscheidet sich für die verschiedenen Arten, wie Transaktionen implementiert werden, dh Schnittstellen-Proxy oder Klassen-Proxy oder AspectJ-Weben. Siehe die Dokumentation .Transactional
Annotation daher nicht nur zum Ändern von Transaktionen empfohlen wird, sondern auch für den Zugriff auf nur solche?Sie können versuchen, einzustellen
in hibernate.cfg.xml oder persistence.xml
Das Problem, das bei dieser Eigenschaft zu beachten ist, wird hier ausführlich erläutert
quelle
<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
hibernate.enable_lazy_load_no_trans
ein Anti-Patterns ist , oder?Der beste Weg, um damit umzugehen,
LazyInitializationException
ist die Verwendung derJOIN FETCH
Direktive:Verwenden Sie auf keinen Fall die folgenden Anti-Patterns, wie in einigen Antworten vorgeschlagen:
hibernate.enable_lazy_load_no_trans
Manchmal ist eine DTO-Projektion die bessere Wahl als das Abrufen von Entitäten, und auf diese Weise erhalten Sie keine
LazyInitializationException
.quelle
FetchType=EAGER
, aber das ist keine richtige Lösung, oder?@Transactional
Dienst verlassen.Ich habe den gleichen Fehler für eine bis viele Beziehungen für die folgenden Anmerkungen erhalten.
Nach dem Hinzufügen von fetch = FetchType.EAGER wie unten geändert, hat es bei mir funktioniert.
quelle
Wenn Sie spring data jpa, spring boot verwenden, können Sie diese Zeile in application.properties hinzufügen
quelle
Diese Ausnahme wird aufgrund des Anrufs
session.getEntityById()
geschlossen. Sie müssen die Entität also erneut an die Sitzung anhängen. Oder Einfache Lösung ist einfach zu konfigurieren ,default-lazy="false"
um Ihreentity.hbm.xml
oder wenn Sie Anmerkungen verwenden fügen Sie einfach@Proxy(lazy=false)
auf Ihre Entity - Klasse.quelle
Ich bin auf das gleiche Problem gestoßen. Ich denke, eine andere Möglichkeit, dies zu beheben, besteht darin, dass Sie die Abfrage so ändern können, dass das Abrufen Ihres Elements aus dem Modell wie folgt erfolgt:
quelle
Dies bedeutet, dass das Objekt, auf das Sie zugreifen möchten, nicht geladen ist. Schreiben Sie daher eine Abfrage, mit der ein Join des Objekts abgerufen wird, auf das Sie zugreifen möchten.
Z.B:
Wenn Sie versuchen, ObjectB von ObjectA abzurufen, wobei ObjectB ein Fremdschlüssel in ObjectA ist.
Abfrage:
quelle
Hier gibt es mehrere gute Antworten, die diesen Fehler in einem weiten Bereich behandeln. Ich bin mit Spring Security auf eine bestimmte Situation gestoßen, die eine schnelle, wenn auch wahrscheinlich nicht optimale Lösung hatte.
Während der Benutzerautorisierung (unmittelbar nach dem Anmelden und dem Übergeben der Authentifizierung) habe ich eine Benutzerentität für eine bestimmte Berechtigung in einer benutzerdefinierten Klasse getestet, die SimpleUrlAuthenticationSuccessHandler erweitert.
Meine Benutzerentität implementiert UserDetails und verfügt über eine Reihe von verzögert geladenen Rollen, die die Ausnahme "org.hibernate.LazyInitializationException - Proxy konnte nicht initialisiert werden - keine Sitzung" ausgelöst haben. Das Ändern dieses Sets von "fetch = FetchType.LAZY" in "fetch = FetchType.EAGER" hat dies für mich behoben.
quelle
Wenn Sie JPQL verwenden, ist die Verwendung von JOIN FETCH der einfachste Weg: http://www.objectdb.com/java/jpa/query/jpql/from#LEFT_OUTER_INNER_JOIN_FETCH_
quelle
Konfrontierte die gleiche Ausnahme in verschiedenen Anwendungsfällen.
Anwendungsfall: Versuchen Sie, Daten aus der Datenbank mit DTO-Projektion zu lesen .
Lösung: Verwenden Sie die Methode get anstelle von load .
Generischer Betrieb
}}
Persistenzklasse
CustomerDAO-Schnittstelle
Objektklasse für Entitätsübertragung
}}
Fabrikklasse
}}
Entitätsspezifisches DAO
}}
Daten abrufen: Testklasse
Aktuelle Daten
Abfrage und Ausgabe von Hibernate System generiert
Ruhezustand: Wählen Sie customer0_.Id als Id1_0_0_, customer0_.City als City2_0_0_, customer0_.Name als Name3_0_0_ aus CustomerLab31 customer0_ aus, wobei customer0_.Id =?
Kundenname -> Cody, CustomerCity -> LA
quelle
Wenn Sie
Grail's
Framework verwenden, ist es einfach, eine verzögerte Initialisierungsausnahme mithilfe von zu behebenLazy
Schlüsselworts für ein bestimmtes Feld in der Domänenklasse .Zum Beispiel:
Weitere Informationen finden Sie hier
quelle
In meinem Fall verursachte ein Verlegter
session.clear()
dieses Problem.quelle
Dies bedeutet, dass Sie JPA oder Ruhezustand in Ihrem Code verwenden und Änderungsvorgänge für die Datenbank ausführen, ohne die Geschäftslogiktransaktion durchzuführen. Eine so einfache Lösung hierfür ist, Ihren Code @Transactional zu markieren
quelle
verwendet session.get (*. class, id); aber keine Funktion laden
quelle
Sie können es auch lösen, indem Sie lazy = false in Ihre * .hbm.xml-Datei einfügen, oder Sie können Ihr Objekt in Hibernate.init (Object) initiieren, wenn Sie ein Objekt von db erhalten
quelle
Nehmen Sie die folgenden Änderungen in servlet-context.xml vor
quelle