Otrzymuję następujący wyjątek:
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)
kiedy próbuję zadzwonić z głównego, następujące linie:
Model subProcessModel = getModelByModelGroup(1112);
System.out.println(subProcessModel.getElement().getNote());
Zaimplementowałem tę getModelByModelGroup(int modelgroupid)
metodę po pierwsze:
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;
}
}
i dostałem wyjątek. Następnie przyjaciel zaproponował mi, żebym zawsze testował sesję i pobierał bieżącą sesję, aby uniknąć tego błędu. Więc zrobiłem to:
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;
}
}
}
ale nadal otrzymujesz ten sam błąd. Dużo czytałem o tym błędzie i znalazłem kilka możliwych rozwiązań. Jednym z nich było ustawienie lazyLoad na false, ale nie wolno mi tego robić, dlatego zaproponowano mi kontrolowanie sesji
Jeśli użyjesz Spring oznacz klasę jako @Transactional , to Spring zajmie się zarządzaniem sesjami.
Za pomocą
@Transactional
wielu ważnych aspektów, takich jak propagacja transakcji, obsługiwane są automatycznie. W takim przypadku, jeśli zostanie wywołana inna metoda transakcyjna, będzie ona miała możliwość dołączenia do bieżącej transakcji, unikając wyjątku „bez sesji”.OSTRZEŻENIE Jeśli używasz
@Transactional
, pamiętaj o wynikającym z tego zachowaniu. W tym artykule znajdziesz typowe pułapki. Na przykład aktualizacje jednostek są utrzymywane, nawet jeśli nie wywołujesz jawnie połączeniasave
źródło
@EnableTransactionManagement
do konfiguracji, aby umożliwić transakcje. „ jeśli nazywa się inną metodę transakcyjną, metoda będzie miała opcję dołączenia do bieżącej transakcji ”, to zachowanie jest różne dla różnych sposobów realizacji transakcji, tj. proxy interfejsu vs proxy klasy lub tkanie AspectJ. Zapoznaj się z dokumentacją .Transactional
adnotacja z wiosny jest zatem zalecana nie tylko do modyfikowania transakcji, ale także do uzyskiwania dostępu tylko do nich?Możesz spróbować ustawić
w hibernacji.cfg.xml lub persistence.xml
Problem, o którym należy pamiętać z tą właściwością, jest dobrze wyjaśniony tutaj
źródło
<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
hibernate.enable_lazy_load_no_trans
to anty-wzory , prawda?Najlepszym sposobem na poradzenie sobie z tym
LazyInitializationException
jest skorzystanie zJOIN FETCH
dyrektywy:W każdym razie NIE używaj następujących Anti-Patternów, jak sugerują niektóre odpowiedzi:
hibernate.enable_lazy_load_no_trans
Czasami projekcja DTO jest lepszym wyborem niż pobieranie encji, w ten sposób nie dostaniesz żadnej
LazyInitializationException
.źródło
FetchType=EAGER
, ale to nie jest poprawne rozwiązanie, prawda?@Transactional
usługi.Otrzymałem ten sam błąd dla relacji jeden do wielu dla poniższych adnotacji.
Zmieniono jak poniżej po dodaniu fetch = FetchType.EAGER, działało to dla mnie.
źródło
jeśli używasz danych wiosennych jpa, rozruchu wiosennego, możesz dodać ten wiersz w pliku application.properties
źródło
Ten wyjątek ze względu na to, że kiedy zadzwonisz
session.getEntityById()
, sesja zostanie zamknięta. Musisz więc ponownie dołączyć encję do sesji. Lub Łatwe rozwiązanie to po prostu skonfigurujdefault-lazy="false"
do swojegoentity.hbm.xml
lub jeśli używasz adnotacji, po prostu dodaj@Proxy(lazy=false)
do swojej klasy encji.źródło
Napotkałem ten sam problem. Myślę, że innym sposobem na to jest to, że możesz zmienić zapytanie, aby dołączyć, aby pobrać Element z Modelu w następujący sposób:
źródło
Oznacza to, że obiekt, do którego próbujesz uzyskać dostęp, nie jest ładowany, więc napisz zapytanie, które pobierze sprzężenie z obiektem, do którego próbujesz uzyskać dostęp.
Na przykład:
Jeśli próbujesz uzyskać ObjectB z ObjectA, gdzie ObjectB jest kluczem obcym w ObjectA.
Zapytanie:
źródło
Jest tu kilka dobrych odpowiedzi, które radzą sobie z tym błędem w szerokim zakresie. W Spring Security natrafiłem na konkretną sytuację, która szybko i pewnie nie była optymalna.
Podczas autoryzacji użytkownika (natychmiast po zalogowaniu i przejściu uwierzytelnienia) testowałem encję użytkownika pod kątem określonych uprawnień w klasie niestandardowej, która rozszerza SimpleUrlAuthenticationSuccessHandler.
Moja jednostka użytkownika implementuje UserDetails i ma zestaw Leniwie załadowanych ról, które zgłosiły wyjątek „org.hibernate.LazyInitializationException - nie można zainicjować proxy - brak sesji”. Zmiana tego zestawu z „fetch = FetchType.LAZY” na „fetch = FetchType.EAGER” naprawiła to dla mnie.
źródło
Jeśli używasz JPQL, użyj JOIN FETCH jest najprostszym sposobem: http://www.objectdb.com/java/jpa/query/jpql/from#LEFT_OUTER_INNER_JOIN_FETCH_
źródło
Napotkano ten sam wyjątek w innym przypadku użycia.
Przypadek użycia: Spróbuj odczytać dane z DB z projekcją DTO.
Rozwiązanie: Użyj metody get zamiast ładowania .
Ogólne działanie
}
Klasa trwałości
Interfejs CustomerDAO
Klasa obiektu transferu jednostki
}
Klasa fabryczna
}
DAO specyficzne dla jednostki
}
Pobieranie danych: klasa testowa
Obecne dane
Zapytania i dane wyjściowe generowane przez system hibernacji
Hibernacja: wybierz klienta0_.Id jako Id1_0_0_, customer0_.City jako City2_0_0_, customer0_.Nazwa jak Name3_0_0_ z CustomerLab31 customer0_ gdzie where0_0_.Id =?
CustomerName -> Cody, CustomerCity -> LA
źródło
Jeśli używasz
Grail's
frameworka, łatwo jest rozwiązać leniwy wyjątek inicjujący , używającLazy
słowa kluczowego w określonym polu w klasie domeny.Na przykład:
Znajdź więcej informacji tutaj
źródło
W moim przypadku
session.clear()
przyczyną tego problemu było niewłaściwe umieszczenie .źródło
Oznacza to, że używasz JPA lub hibernacji w swoim kodzie i wykonujesz operację modyfikacji na DB bez dokonywania transakcji logiki biznesowej. Tak prostym rozwiązaniem jest zaznaczenie swojego kodu @Transactional
źródło
używa session.get (*. class, id); ale nie ładuj funkcji
źródło
możesz również rozwiązać ten problem, dodając lazy = false do pliku * .hbm.xml lub możesz zainicjować swój obiekt w Hibernate.init (Object), gdy otrzymasz obiekt z db
źródło
Wykonaj następujące zmiany w pliku servlet-context.xml
źródło