通过将Spring MVC与AJAX/JSON和MappingJackson一起使用来实现LazyInitializationException

Tim*_*Tim 1 java hibernate spring-mvc jackson

我正在使用Spring MVC,AJAX/JSON和Hibernate从MySQL数据库中获取所有人员.我写了JUnit集成测试来验证我的服务,一切都没问题.

现在我称之为:

@RequestMapping(value="/allpersons", method=RequestMethod.GET)
public @ResponseBody Set<Person> getAllPersons() {
    Set<Person> persons= new PersonServiceImpl().getAllPersons();
    return persons;
}
Run Code Online (Sandbox Code Playgroud)

我调试了它.这条线

return persons;
Run Code Online (Sandbox Code Playgroud)

一切都好.我有一个包含所有人的HashSet.调试更多步骤,我来到这一行:

this.objectMapper.writeValue(jsonGenerator, o);
Run Code Online (Sandbox Code Playgroud)

org.springframework.http.converter.json.MappingJacksonHttpMessageConverter
Run Code Online (Sandbox Code Playgroud)

然后我没有看到源代码,但我的调试器告诉我:

StdSerializerProvider._serializeValue(JsonGenerator, Object) line 297
Run Code Online (Sandbox Code Playgroud)

在这一行之后,我得到错误:

ERROR: org.hibernate.LazyInitializationException - failed to lazily initialize a collection of role: com.mydomain.project.dom.Person.projects, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.mydomain.project.dom.Person.projects, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
    at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:186)
    at org.codehaus.jackson.map.ser.ContainerSerializers$CollectionSerializer.serializeContents(ContainerSerializers.java:339)
    at org.codehaus.jackson.map.ser.ContainerSerializers$CollectionSerializer.serializeContents(ContainerSerializers.java:314)
    at org.codehaus.jackson.map.ser.ContainerSerializers$AsArraySerializer.serialize(ContainerSerializers.java:112)
    at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:268)
    at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:160)
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:131)
    at org.codehaus.jackson.map.ser.ContainerSerializers$CollectionSerializer.serializeContents(ContainerSerializers.java:363)
    at org.codehaus.jackson.map.ser.ContainerSerializers$CollectionSerializer.serializeContents(ContainerSerializers.java:314)
    at org.codehaus.jackson.map.ser.ContainerSerializers$AsArraySerializer.serialize(ContainerSerializers.java:112)
    at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:297)
    at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:224)
    at org.codehaus.jackson.map.ObjectMapper.writeValue(ObjectMapper.java:1030)
    at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.writeInternal(MappingJacksonHttpMessageConverter.java:153)
    at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:181)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.writeWithMessageConverters(AnnotationMethodHandlerAdapter.java:975)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.handleResponseBody(AnnotationMethodHandlerAdapter.java:933)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.getModelAndView(AnnotationMethodHandlerAdapter.java:882)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:428)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
    at org.tuckey.web.filters.urlrewrite.NormalRewrittenUrl.doRewrite(NormalRewrittenUrl.java:195)
    at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:159)
    at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:141)
    at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:90)
    at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:417)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:619)

看起来,这与序列化/ JacksonMapping有关.它想要得到一个人的相关项目,这些项目是不需要的,而且通常是懒惰的.

这有什么问题?

提前谢谢你和最诚挚的问候.

oct*_*tav 8

您遇到的情况与此类似: 延迟加载错误

简而言之,您正在访问Hibernate Session之外的延迟加载集合.

可能的解决方案:

  • 急切地抓住它
  • 确保您的Hibernate会话在您访问该集合时仍处于打开状态.您可以使用OpenSessionInView过滤器.这本身可能还不够,因为Hibernate可能会结束你关闭交易的会话.因此,您需要扩展事务范围或找到一种方法来阻止Hibernate在事务结束时关闭会话.
  • 确保您访问事务中的延迟加载集合,以确保Hibernate加载它.

请查看上面指定的帖子了解更多详情.

更新1根据我的理解,这是由杰克逊映射器接收未完全加载的模型(某些集合是延迟加载)引起的.你说你不需要杰克逊映射那些集合中的对象.我看到的替代方案是:

  • 给杰克逊一个正确的模型,基于你的Person对象创建的简单POJO,只包含你要用Jackson映射的信息.因此,不是给杰克逊一个人员列表,而是给它一个PersonDetails列表(或者你想给他们打电话)
  • 配置杰克逊忽略该集合 - 不确定是否可能

希望这可以帮助.