LazyInitializationException с использованием Spring MVC с AJAX / JSON & MappingJackson - PullRequest
1 голос
/ 07 декабря 2010

Я использую 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;
}

Я отладил это. Линия с

return persons;

все хорошо. У меня есть HashSet со всеми людьми в нем. Отлаживая больше шагов, я прихожу к этой строке:

this.objectMapper.writeValue(jsonGenerator, o);

в

org.springframework.http.converter.json.MappingJacksonHttpMessageConverter

Тогда я не вижу исходный код, но мой отладчик говорит мне:

StdSerializerProvider._serializeValue(JsonGenerator, Object) line 297

После этой строки я получаю сообщение об ошибке:

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. Он хочет получить связанные с ним проекты человека, которые не нужны и обычно загружаются лениво.

В чем здесь проблема?

Заранее спасибо и наилучшими пожеланиями.

Ответы [ 4 ]

8 голосов
/ 07 декабря 2010

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

В двух словах, вы получаете доступ к загруженной отложенной коллекции коллекции вне сеанса Hibernate.

Возможнорешения:

  • получите его с нетерпением
  • убедитесь, что сеанс Hibernate все еще открыт в точке доступа к коллекции.Вы можете использовать фильтр OpenSessionInView.Этого само по себе может быть недостаточно, поскольку Hibernate может завершить сеанс, в котором вы закрываете транзакцию.Поэтому вам нужно будет расширить область своих транзакций или найти способ запретить Hibernate закрывать сеанс после завершения транзакции.
  • убедитесь, что вы обращаетесь к коллекции с отложенной загрузкой внутри транзакции, чтобы Hibernate загружал ее.

Пожалуйста, проверьте сообщение, указанное выше, для получения более подробной информации.

ОБНОВЛЕНИЕ 1 Из того, что я понял, это связано с тем, что картограф Джексона получил модель, которая не была полностью загружена (некоторые коллекцииленивы загружены).Вы говорите, что Джексону не нужно отображать объекты в этих коллекциях.Альтернативы, которые я вижу:

  • Дайте Джексону правильную модель, простые POJO, созданные на основе ваших объектов Person, содержащие только информацию, которую вы хотите сопоставить с Джексоном.Таким образом, вместо того, чтобы дать Джексону список Persons, вы дадите ему список PersonDetails (или как вы хотите их вызывать)
  • Настройте Джексона на игнорирование этой коллекции - не уверен, возможно ли это

Надеюсь, это поможет.

2 голосов
/ 15 сентября 2014

Если вы не хотите отображать в своем объекте JSON поле, которое связано в спящем режиме, вы можете добавить аннотацию "@JsonIgnore" в классе вашей модели:

@JsonIgnore
@OneToMany(mappedBy = "person")
private List<ProjectEntity> projects = new ArrayList<ProjectEntity>();
2 голосов
/ 10 декабря 2010

Хотя это не сразу помогает вам с легкостью, может быть полезно знать, что существует новый проект, связанный с Джексоном, jackson-module-hibernate (в GitHub), который призван решить эту проблему проблема наряду с другими обычно проблемными случаями использования.

Но в краткосрочной перспективе эта статья может оказаться полезной: http://kyrill007.livejournal.com/2577.html

0 голосов
/ 30 октября 2013
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...