Jak naprawić org.hibernacja.LazyInitializationException - could not initialize proxy-no Session

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ę wywołać z main następujące linie:

Model subProcessModel = getModelByModelGroup(1112);
System.out.println(subProcessModel.getElement().getNote());

Zaimplementowałem metodę getModelByModelGroup(int modelgroupid) najpierw tak:

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ł wyjątek. Następnie przyjaciel zasugerował mi, aby zawsze testować sesję i uzyskać 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, uzyskać ten sam błąd. Czytałem dużo na ten błąd i znalazłem kilka możliwych rozwiązań. Jednym z nich było ustaw lazyLoad na false, ale nie mogę tego zrobić, dlatego zasugerowano mi kontrolowanie sesji

Author: Max, 2014-02-05

19 answers

Błędem jest to, że Konfiguracja zarządzania sesją jest ustawiona na zamknięcie sesji podczas zatwierdzania transakcji. Sprawdź czy masz coś takiego:

<property name="current_session_context_class">thread</property>

W Twojej konfiguracji.

Aby rozwiązać ten problem, można zmienić konfigurację fabryki sesji lub otworzyć inną sesję i tylko wtedy poprosić o te leniwe ładowane obiekty. Ale sugerowałbym tutaj zainicjowanie tej leniwej kolekcji w getModelByModelGroup i wywołanie:

Hibernate.initialize(subProcessModel.getElement());

Kiedy jesteś jeszcze w aktywnej sesji.

I jeszcze jedno. Przyjacielska Rada. Masz coś takiego w swojej metodzie:
for (Model m : modelList) {
    if (m.getModelType().getId() == 3) {
        model = m;
        break;
    }
}

Proszę wstawić ten kod po prostu filtruj te modele o ID typu równym 3 w instrukcji query tylko kilka linijek powyżej.

Trochę więcej czytania:

Konfiguracja fabryczna sesji

Problem z zamkniętą sesją

 97
Author: goroncy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-04 08:45:38

Jeśli używasz Springa oznaczyć klasę jako @ Transactional , to Spring zajmie się zarządzaniem sesją.

@Transactional
public class MyClass {
    ...
}

Za pomocą @Transactional wiele ważnych aspektów, takich jak propagacja transakcji, jest obsługiwanych automatycznie. W tym przypadku, jeśli zostanie wywołana inna metoda transakcyjna, metoda będzie miała możliwość dołączenia do trwającej transakcji, unikając wyjątku "brak sesji".

Ostrzeżenie Jeśli używasz @Transactional, pamiętaj o wynikowym zachowaniu. Zobacz też Ten artykuł na typowe pułapki. Na przykład aktualizacje encji są utrzymywane nawet jeśli nie wywołujesz jawnie save

 199
Author: user2601995,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-19 01:04:59

Możesz spróbować ustawić

<property name="hibernate.enable_lazy_load_no_trans">true</property>

W hibernacji.cfg.xml lub persistence.xml

Problem, o którym należy pamiętać z tą właściwością są dobrze wyjaśnione tutaj

 104
Author: Wilianto Indrawan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:59

Najlepszym sposobem obsługi LazyInitializationException jest użycie JOIN FETCH dyrektywy:

Query query = session.createQuery("""
    select m
    from Model m
    join fetch m.modelType
    where modelGroup.id = :modelGroupId
    """
);

W każdym razie, nie używaj następujących anty-wzorców, jak sugerują niektóre odpowiedzi:

Czasami projekcja DTO jest lepszym Wyborem niż pobieranie Bytów, a w ten sposób nie otrzymasz żadnych LazyInitializationException.

 71
Author: Vlad Mihalcea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-08 21:07:24

Otrzymywałem ten sam błąd dla relacji jeden do wielu Dla poniższej adnotacji.

@OneToMany(mappedBy="department", cascade = CascadeType.ALL)

Zmieniony jak poniżej po dodaniu fetch=FetchType.EAGER, zadziałało na mnie.

@OneToMany(mappedBy="department", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
 22
Author: Smruti R Tripathy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-30 18:18:02

Jeśli używasz spring data jpa, spring boot możesz dodać tę linię w aplikacji.właściwości

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
 16
Author: Shaaban Ebrahim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-15 21:24:54

Ten wyjątek z powodu wywołania session.getEntityById(), sesja zostanie zamknięta. Musisz więc ponownie dołączyć obiekt do sesji. Lub łatwym rozwiązaniem jest po prostu skonfiguruj {[1] } do swojej entity.hbm.xml lub jeśli używasz adnotacji, po prostu dodaj @Proxy(lazy=false) do swojej klasy encji.

 9
Author: R Pidugu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-07 14:37:17

Napotkałem ten sam problem. Myślę, że innym sposobem, aby to naprawić jest to, że można zmienić zapytanie do join fetch twój Element z modelu w następujący sposób:

Query query = session.createQuery("from Model m join fetch m.element where modelGroup.id = :modelGroupId")
 5
Author: Tony Vu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-13 08:44:41

Oznacza to, że obiekt, do którego próbujesz uzyskać dostęp, nie jest załadowany, więc napisz zapytanie, które spowoduje, że połączy się z obiektem, do którego próbujesz uzyskać dostęp.

Eg:

Jeśli próbujesz pobrać ObjectB z ObjectA, gdzie ObjectB jest kluczem obcym w ObjectA.

Zapytanie:

SELECT objA FROM ObjectA obj JOIN FETCH obj.objectB objB
 5
Author: rex roy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-23 11:36:11

Istnieje kilka dobrych odpowiedzi, które obsługują ten błąd w szerokim zakresie. Natknąłem się na konkretną sytuację Z Spring Security, która miała szybką, choć prawdopodobnie nie optymalną, naprawę.

Podczas autoryzacji użytkownika (bezpośrednio po zalogowaniu i przejściu uwierzytelniania) testowałem jednostkę użytkownika dla określonego organu w niestandardowej klasie, która rozszerza Simpleurlauthenticationsukcesshandler.

My user entity implementuje UserDetails i ma zestaw leniwych załadowanych ról który rzucił " org.hibernacja.LazyInitializationException - could not initialize proxy-no Session" wyjątek. Zmiana tego zestawu z "fetch=FetchType.Leniwe " do " fetch=FetchType.EAGER " naprawił to dla mnie.

 3
Author: Night Owl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-15 01:55:36

Ten sam wyjątek w różnych przypadkach użycia.

Tutaj wpisz opis obrazka

Przypadek użycia: spróbuj odczytać dane z DB z projekcją DTO .

Rozwiązanie: użyj metody get zamiast load .

Operacja Generyczna

public class HibernateTemplate {
public static Object loadObject(Class<?> cls, Serializable s) {
    Object o = null;
    Transaction tx = null;
    try {
        Session session = HibernateUtil.getSessionFactory().openSession();
        tx = session.beginTransaction();
        o = session.load(cls, s); /*change load to get*/
        tx.commit();
        session.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return o;
}

}

Klasa Trwałości

public class Customer {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id")
private int customerId;

@Column(name = "Name")
private String customerName;

@Column(name = "City")
private String city;

//constructors , setters and getters

}

CustomerDAO interface

public interface CustomerDAO 
     {
   public CustomerTO getCustomerById(int cid);
     }

Obiekt Transferu Encji Klasa

public class CustomerTO {

private int customerId;

private String customerName;

private String city;

//constructors , setters and getters

}

Klasa Fabryczna

public class DAOFactory {

static CustomerDAO customerDAO;
static {
    customerDAO = new HibernateCustomerDAO();
}

public static CustomerDAO getCustomerDAO() {
    return customerDAO;
}

}

Entity specific DAO

public class HibernateCustomerDAO implements CustomerDAO {

@Override
public CustomerTO getCustomerById(int cid) {
    Customer cust = (Customer) HibernateTemplate.loadObject(Customer.class, cid);
    CustomerTO cto = new CustomerTO(cust.getCustomerId(), cust.getCustomerName(), cust.getCity());
    return cto;
}

}

Pobieranie danych: Klasa testowa

CustomerDAO cdao = DAOFactory.getCustomerDAO();
CustomerTO c1 = cdao.getCustomerById(2);
System.out.println("CustomerName -> " + c1.getCustomerName() + " ,CustomerCity -> " + c1.getCity());

Obecne Dane

Tutaj wpisz opis obrazka

Zapytanie i wyjście generowane przez system Hibernate

Hibernate: wybierz customer0_.Id jako Id1_0_0_, customer0_.Miasto jako City2_0_0_, customer0_.Name jako Nazwa3_0_0_ z CustomerLab31 customer0_ gdzie customer0_.Id=?

CustomerName -> Cody ,CustomerCity - > LA

 3
Author: Kms,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-14 19:18:36

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_

 2
Author: xihui,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-23 21:55:05

Jeśli używasz frameworka Grail's, łatwo jest rozwiązać leniwy wyjątek inicjalizacji używając słowa kluczowego Lazy w określonym polu w klasie Domain.

For-example:

class Book {
    static belongsTo = [author: Author]
    static mapping = {
        author lazy: false
    }
}

Więcej informacji znajdziesz tutaj

 1
Author: Zeb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-27 12:38:04

W moim przypadku zagubione session.clear() powodowało ten problem.

 1
Author: absin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-30 14:04:14

Oznacza to, że używasz JPA lub hibernate w kodzie i wykonujesz modyfikację na DB bez dokonywania transakcji logiki biznesowej. Tak prostym rozwiązaniem jest zaznaczenie fragmentu kodu @ Transactional

 1
Author: Aman Goel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-31 04:05:25

Przydarzyło mi się to, gdy korzystałem już z @Transactional(value=...) i korzystałem z wielu menedżerów transakcji.

Moje formularze wysyłały dane, które już na nich były @JsonIgnore, więc dane wysyłane z formularzy były niekompletne.

Początkowo używałem rozwiązania anty pattern, ale okazało się, że było niesamowicie powolne. Wyłączyłem to ustawiając na false.

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false

Poprawka miała na celu zapewnienie, że wszystkie obiekty, które miały leniwie załadowane dane, które nie były ładowane, zostały pobrane z bazy danych najpierw.

Optional<Object> objectDBOpt = objectRepository.findById(object.getId());

if (objectDBOpt.isEmpty()) {
    // Throw error
} else {
    Object objectFromDB = objectDBOpt.get();
}

Krótko mówiąc, jeśli wypróbowałeś wszystkie inne odpowiedzi, po prostu sprawdź, czy najpierw wczytywasz się z bazy danych, jeśli nie podałeś wszystkich właściwości @JsonIgnore i używasz ich w zapytaniu bazy danych.

 0
Author: Nightfa11,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-14 00:37:41

Używa sesji.get(*.class, id); ale nie ładuj funkcji

 -1
Author: Artavazd Manukyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-25 21:21:21

Można również rozwiązać go dodając lazy=false do swojego *.hbm.plik xml lub można init obiektu w Hibernate.init (Object) gdy otrzymujesz obiekt z db

 -2
Author: Sandeep Roniyaar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-31 10:12:07

Wykonaj następujące zmiany w Servlet-context.xml

    <beans:property name="hibernateProperties">
        <beans:props>

            <beans:prop key="hibernate.enable_lazy_load_no_trans">true</beans:prop>

        </beans:props>
    </beans:property>
 -2
Author: ArunDhwaj IIITH,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-09 00:29:58