LazyInitializationException mithilfe von Spring MVC mit AJAX / JSON & MappingJackson
-
09-10-2019 - |
Frage
Ich bin mit Spring MVC, AJAX / JSON und Hibernate alle Personen aus einer MySQL-Datenbank zu erhalten. Ich schrieb Tests JUnit Integration meinen Dienst zu überprüfen, und alles ist in Ordnung.
Jetzt nenne ich es in dieser Art:
@RequestMapping(value="/allpersons", method=RequestMethod.GET)
public @ResponseBody Set<Person> getAllPersons() {
Set<Person> persons= new PersonServiceImpl().getAllPersons();
return persons;
}
Ich gedebuggt es. Die Zeile mit
return persons;
alles ist in Ordnung. Ich habe einen HashSet mit allen Menschen in ihm. Debuggen von mehreren Schritten, komme ich zu dieser Zeile:
this.objectMapper.writeValue(jsonGenerator, o);
in
org.springframework.http.converter.json.MappingJacksonHttpMessageConverter
Dann sehe ich nicht den Quellcode, aber mein Debugger sagt mir:
StdSerializerProvider._serializeValue(JsonGenerator, Object) line 297
Nach dieser Zeile, erhalte ich die Fehlermeldung:
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)
Es scheint, also hat etwas mit der Serialisierung / JacksonMapping zu tun. Sie will die damit verbundenen Projekte einer Person erhalten, die nicht benötigt werden, und sie werden in der Regel träge geladen.
Was ist das Problem hier?
Vielen Dank im Voraus & Mit freundlichen Grüßen.
Lösung
Was Sie begegnen, ist ähnlich mit diesem: Lazy Loading-Fehler
Auf den Punkt gebracht, Sie sind ein fauler-loaded Sammlung außerhalb der Hibernate Session zugreifen.
Mögliche Lösungen:
- holen sie eifrig
- stellen Sie sicher, Ihre Hibernate Session ist noch offen an dem Punkt, wo Sie die Sammlung zugreifen. Sie können OpenSessionInView Filter verwenden. Das allein kann nicht genug sein, wie Hibernate kann Ihre Sitzung beenden, wo Sie Ihre Transaktion zu schließen. So müssen Sie Ihren Transaktionsbereich erweitern oder eine Art und Weise zu verhindern, dass Hibernate finden die Sitzung auf Transaktionsende zu schließen.
- Sie unbedingt die lazy-loaded Sammlung in Ihrer Transaktion zugreifen, um sicherzustellen, dass Hibernate lädt sie zu machen.
Bitte lesen Sie die Post oben angegebenen für weitere Details.
UPDATE 1 Von dem, was ich verstanden habe, was durch den Jackson-Mapper verursacht wird ein Modell erhalten, die nicht vollständig geladen wurde (einige Sammlungen sind faul geladen). Du sagst, du nicht die Objekte in diesen Sammlungen müssen von Jackson abgebildet werden. Die Alternativen ich sehe sind:
- Geben Jackson ein korrektes Modell, einfache POJOs erstellt auf der Grundlage Ihrer Person Objekte, die nur die Informationen, die Sie mit Jackson zuordnen möchten. Anstatt also gibt Jackson eine Liste von Personen, Sie geben ihm eine Liste von PersonDetails (oder wie Sie wollen, sie nennen)
- Konfigurieren Jackson dass die Sammlung zu ignorieren - nicht sicher, ob das möglich ist
Hope, das hilft.
Andere Tipps
Während dies nicht sofort Ihnen mit der leicht zu helfen, kann es gut zu wissen, dass es ein neues Jackson-Projekt ist, jackson-module-Hibernate (bei GitHub), den Zielen dieses Problem zusammen mit anderen häufig problematischen Anwendungsfällen zu lösen.
Aber auf kurze Sicht, könnten Sie diesen Artikel nützlich finden: http://kyrill007.livejournal.com/ 2577.html
Wenn Sie nicht in Sie sind JSON-Objekt, das Feld zugeordnet werden soll, die in Hibernate Beziehung verknüpft ist, können Sie Annotations „@JsonIgnore“ in der Modellklasse hinzuzufügen:
@JsonIgnore
@OneToMany(mappedBy = "person")
private List<ProjectEntity> projects = new ArrayList<ProjectEntity>();
verwenden. Das hat für mich gearbeitet.