hibernate查询懒加载数据返回json时抛出异常
hibernate查询懒加载数据时。例如springmvc,return返回对象jackson转json时,懒加载会抛出会抛出异常。
用jackson-datatype-hibernate的ObjectMapper和Hibernate4Module解决懒加载转json的问题。jackson-datatype-hibernate支持JSON序列化和反序列化hibernate特定的数据类型和性质,特别是懒加载等方面。
问题简说
Teacher.java
@OneToMany(fetch= FetchType.LAZY,cascade = CascadeType.ALL) @JoinColumn(name="teacher_id") public Set<Student> getStudents() { return students; }
Student.java
@ManyToOne @JoinColumn(name="teacher_id") public Teacher getTeacher() { return teacher; }
StudentServiceImpl.java
@Override @Transactional(readOnly = true) public Student findById(Long id){ Student student = studentRepository.findOne(id); return student; }
IndexController.java
@RequestMapping(value = "/find", method = RequestMethod.GET) @ResponseBody public Student find(HttpServletRequest request, HttpServletResponse response){ Student student = studentService.findById(1L); return student; }
调试如图
由于查询使用了懒加载,如获取的数据并没有真的获取,在使用@ResponseBody返回json的数据,会抛出异常Could not write content: failed to lazily initialize a collection of role。
解决办法
使用jackson-datatype-hibernate可以解决该问题。
第一步:
引入:jackson-datatype-hibernate4-2.9.3.jar
maven:
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-hibernate4</artifactId> <version>2.9.3</version> </dependency>
第二步:
新建HibernateAwareObjectMapper类,继承ObjectMapper
package com.weizhixi.util; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module; public class HibernateAwareObjectMapper extends ObjectMapper { public HibernateAwareObjectMapper() { Hibernate4Module h4 = new Hibernate4Module(); registerModule(h4); } }
第三步:
在spring配置MappingJackson2HttpMessageConverter配置里加入以下代码:
<property name="objectMapper">
<bean class="com.weizhixi.util.HibernateAwareObjectMapper" />
</property>
完整示例:
<!--依赖注入--> <mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <!--防止请求和响应乱码 默认--> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="defaultCharset" value="UTF-8" /> <property name="writeAcceptCharset" value="false" /> </bean> <!--防止请求和响应乱码 JSON--> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="defaultCharset" value="UTF-8" /> <!-- Use the HibernateAware mapper instead of the default --> <property name="objectMapper"> <bean class="com.weizhixi.util.HibernateAwareObjectMapper" /> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
运行调试:
{"id":1,"name":"Student-1","teacher":{"id":1,"name":"Teacher","students":null}}
已经正常输出。
参考资料:https://github.com/FasterXML/jackson-datatype-hibernate
参考异常
org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: failed to lazily initialize a collection of role: com.weizhixi.entity.Teacher.students, could not initialize proxy - no Session (through reference chain: com.weizhixi.entity.Student["teacher"]->com.weizhixi.entity.Teacher["students"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.weizhixi.entity.Teacher.students, could not initialize proxy - no Session (through reference chain: com.weizhixi.entity.Student["teacher"]->com.weizhixi.entity.Teacher["students"]) org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:273) org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:100) org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:232) org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:173) org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81) org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:130) org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) javax.servlet.http.HttpServlet.service(HttpServlet.java:624) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) javax.servlet.http.HttpServlet.service(HttpServlet.java:731) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.weizhixi.entity.Teacher.students, could not initialize proxy - no Session (through reference chain: com.weizhixi.entity.Student["teacher"]->com.weizhixi.entity.Teacher["students"]) com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:210) com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:177) com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:190) com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:671) com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:156) com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:575) com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:663) com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:156) com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:129) com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:851) org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:266) org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:100) org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:232) org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:173) org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81) org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:130) org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) javax.servlet.http.HttpServlet.service(HttpServlet.java:624) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) javax.servlet.http.HttpServlet.service(HttpServlet.java:731) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
原创文章,转载请注明出处:https://www.weizhixi.com/article/65.html