орг.зимовать.LazyInitializationException - не удалось инициализировать прокси - нет сессии



я получаю следующее исключение:



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)


когда я пытаюсь позвонить из main следующие строки:



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


я реализовал getModelByModelGroup(int modelgroupid) способ во-первых, как это :



    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);
@SuppressWarnings("unchecked")
List<Model> modelList = (List<Model>)query.list();
Model model = null;
// Cerco il primo Model che è in esercizio: idwf_model_type = 3
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;
}


и есть исключение. Затем друг предложил мне всегда тестировать сеанс и получить текущий сеанс, чтобы избежать этой ошибки. Так я и сделал:



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);
@SuppressWarnings("unchecked")
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;
}

}


но все равно получаю ту же ошибку.
Я много читал об этой ошибке и нашел некоторые возможные решения. Один из них должен был установить lazyLoad в false, но мне не разрешено это делать, поэтому мне было предложено контролировать сеанс

659   15  

15 ответов:

что здесь неправильно, так это то, что ваша конфигурация управления сеансами настроена на закрытие сеанса при фиксации транзакции. Проверьте, если у вас есть что-то вроде:

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

в вашей конфигурации.

чтобы преодолеть эту проблему, вы можете изменить конфигурацию фабрики сеансов или открыть другой сеанс и только попросить эти ленивые загруженные объекты. Но то, что я предлагаю здесь, чтобы инициализировать этот ленивый коллекция в себя getModelByModelGroup и звоните:

Hibernate.initialize(subProcessModel.getElement());

когда вы все еще находитесь в активном сеансе.

и последнее. дружеский Совет. У вас есть что-то вроде этого в вашем методе:

            for (Model m : modelList)
            if (m.getModelType().getId() == 3) {
                model = m;
                break;
            }

пожалуйста, вместо этого кода просто отфильтруйте эти модели с идентификатором типа, равным 3 в операторе запроса всего на пару строк выше.

больше читать:

конфигурация фабрики сеанса

проблема с закрытыми сессия

вы можете попробовать указать

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

в спящем режиме.контекстно-свободная грамматика.xml или персистентность.xml

проблема, чтобы иметь в виду с этим свойством хорошо объяснены здесь

Если вы используете Spring, отметьте класс как @Transactional, затем Spring будет обрабатывать управление сеансом.

@Transactional
public class My Class {
    ...
}

С помощью @Transactional, многие важные аспекты, такие как распространение сделки обрабатываются автоматически. В этом случае, если вызывается другой транзакционный метод, метод будет иметь возможность присоединиться к текущей транзакции, избегая исключения "no session".

Я получал ту же ошибку для одного ко многим отношениям для аннотации ниже.

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

изменено, как показано ниже, после добавления fetch=FetchType.Нетерпеливый, это сработало для меня.

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

это исключение из - за того, когда вы звоните session.getEntityById() сессия будет закрыта. Поэтому вам нужно повторно присоединить объект к сеансу. Или простое решение - просто настроить default-lazy="false" на entity.hbm.xml или если вы используете аннотации просто добавить @Proxy(lazy=false) для вашего класса сущностей.

я столкнулся с такой же проблемой. Я думаю, что другой способ исправить это заключается в том, что вы можете изменить запрос, чтобы присоединиться к выборке элемента из модели следующим образом:

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

Если вы используете spring data jpa, spring boot вы можете добавить эту строку в приложение.свойства

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

здесь есть несколько хороших ответов, которые обрабатывают эту ошибку в широком диапазоне. Я столкнулся с конкретной ситуацией с Spring Security, которая имела быстрое, хотя, вероятно, не оптимальное, исправление.

во время авторизации пользователя (сразу после входа в систему и прохождения аутентификации) я тестировал сущность пользователя для определенного права доступа в пользовательском классе, который расширяет SimpleUrlAuthenticationSuccessHandler.

моя пользовательская сущность реализует UserDetails и имеет набор ленивых загружены роли, которые бросил " орг.зимовать.LazyInitializationException - не удалось инициализировать прокси - нет сессии" исключение. Изменение этого набора из "fetch=FetchType.Ленивый " to " fetch=FetchType.Нетерпеливый " исправил это для меня.

Если вы используете JPQL, используйте JOIN FETCH-это самый простой способ: http://www.objectdb.com/java/jpa/query/jpql/from#LEFT_OUTER_INNER_JOIN_FETCH_

Если вы используете Grail's рамки, это просто решить исключение ленивой инициализации С помощью Lazy ключевое слово для конкретного поля в классе домена.

для примера:

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

дополнительная информация здесь

это означает, что объект, к которому вы пытаетесь получить доступ, не загружен, поэтому напишите запрос, который делает join fetch объекта, к которому вы пытаетесь получить доступ.

например:

Если вы пытаетесь получить ObjectB из ObjectA, где ObjectB является внешним ключом в ObjectA.

запрос :

SELECT objA FROM ObjectA obj JOIN FETCH obj.objectB objB

использует сессии.получить.*(class, id); но не загружайте функцию

вы также можете решить эту проблему, добавив lazy=false в свой *.hbm.xml-файл или вы можете инициализировать свой объект в спящем режиме.init (Object) когда вы получаете объект из db

выполните следующие изменения в сервлет-контексте.xml

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

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

        </beans:props>
    </beans:property>

Comments

    Ничего не найдено.