hibernate查询懒加载数据返回json时抛出异常

知兮丶青 异常 · spring
阅读(1139) 2018-01-23
hibernate查询懒加载数据返回json时抛出异常
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;
}

调试如图

failed to lazily initialize.png

由于查询使用了懒加载,如获取的数据并没有真的获取,在使用@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