орг.зимовать.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, но мне не разрешено это делать, поэтому мне было предложено контролировать сеанс
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
вы также можете решить эту проблему, добавив 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