org.hibernate.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) 

当我尝试从主要的以下几行呼叫:

 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; } 

并得到例外。 然后朋友build议我总是testing会话,并获得当前会话,以避免此错误。 所以我这样做了:

 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; } } 

但仍然得到相同的错误。 我一直在阅读很多这个错误,并find了一些可能的解决scheme。 其中之一是将lazyLoad设置为false,但我不能这样做,为什么我build议控制会话

这里有什么问题是,当你提交事务时,你的会话pipe理configuration被设置为closures会话。 检查你是否有类似的东西:

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

在你的configuration中。

为了克服这个问题,你可以改变会话工厂的configuration或者打开另一个会话,而不是要求那些懒加载的对象。 但是我在这里build议的是在getModelByModelGroup本身中初始化这个懒集合,并调用:

 Hibernate.initialize(subProcessModel.getElement()); 

当你还在活动时。

还有最后一件事。 友好的build议。 在你的方法中你有这样的东西:

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

请检查这段代码,只是在查询语句中只用几行代码来过滤那些types为id的模型。

更多阅读:

会话工厂configuration

closures会议的问题

你可以尝试设置

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

在hibernate.cfg.xml或persistence.xml中

请记住这个属性的问题在这里很好的解释

如果您使用Spring将类标记为@Transactional ,那么Spring将处理会话pipe理。

 @Transactional public class My Class { ... } 

通过使用@Transactional ,事务传播等许多重要方面都会自动处理。 在这种情况下,如果调用另一个事务方法,则该方法可以selectjoin正在进行的事务,避免“无会话”exception。

处理LazyInitializationException的最好方法是使用JOIN FETCH指令:

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

无论如何,请不要使用以下某些答案build议的反模式:

  • 在视图中打开会话
  • hibernate.enable_lazy_load_no_trans

有时候, DTO投影是比获取实体更好的select,这样,您将不会得到任何LazyInitializationException

我遇到了同样的问题。 我认为解决这个问题的另一种方法是,您可以更改查询来连接从模型中获取元素,如下所示:

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

这个exception是因为当你调用session.getEntityById() ,会话将被closures。 所以你需要将实体重新连接到会话。 或者简单的解决scheme就是将default-lazy="false"entity.hbm.xml或者如果使用注释,只需将@Proxy(lazy=false)到实体类中。

这里有几个很好的答案,在广泛的范围内处理这个错误。 我遇到了Spring Security的一个具体情况,虽然可能不是最佳解决scheme,

在用户授权期间(刚刚login并通过身份validation之后),我正在testing用户实体以获取扩展SimpleUrlAuthenticationSuccessHandler的自定义类中的特定权限。

我的用户实体实现UserDetails,并有一个懒惰的加载angular色,抛出了“org.hibernate.LazyInitializationException – 无法初始化代理 – 无会话”exception。 把这个设置从“fetch = FetchType.LAZY”更改为“fetch = FetchType.EAGER”为我解决了这个问题。

如果您正在使用Grail's框架,通过在Domain Class的特定字段上使用Lazy关键字来parsing延迟初始化exception是很简单的。

例如:

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

在这里find更多信息

如果您使用JPQL,使用JOIN FETCH是最简单的方法: http : //www.objectdb.com/java/jpa/query/jpql/from#LEFT_OUTER_INNER_JOIN_FETCH_

对于下面的注释,我得到了一对多关系的错误。

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

在添加fetch = FetchType.EAGER后,如下所示更改,它为我工作。

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

你也可以通过在你的* .hbm.xml文件中添加lazy = false来解决这个问题,或者当你从db获取对象时,你可以在Hibernate.init(Object)中初始化你的对象

使用session.get(*。class,id); 但不要加载function

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>