Spring Boot中 hibernate懒加载(lazy loading)造成序列化失败

字数 441阅读 2473

个人主页:http://hellogod.cn

Spring Boot中 hibernate 延迟加载 | 懒加载(lazy loading)造成序列化失败

Spring hibernate 懒实例化

Spring Boot中 hibernate 延迟加载 | 懒加载(lazy loading)造成序列化失败

问题描述

背景很简单,一个家长(Guardian)对应多个孩子(Student)

首先在家长bean里定义 List<Student> students ,接着通过guardian对象的guardian.getStudents()获取对应的学生对象,按理说没有任何问题

Guardian.java 家长bean

@Entity
@Table(name = "Guardian")
public class Guardian {

    @OneToMany
    private List<Student> students; //学生列表

}

GuardianController.java

@ApiOperation(value = "孩子列表")
    @GetMapping(value = "/children")
    public  List<Student> children(HttpServletRequest request) throws ServletException {

        Guardian guardian = userService.currentGuardian(request);
        return guardian.getStudents();
    }
  • 在IDEA本地运行的时候接口正常:
7FE3731E-DE7B-49BB-A644-941D10D14212
  • 但是奇怪的是部署到服务器Tomcat上之后接口报错:

输出如下:

{
    "timestamp": 1501826190599,
    "status": 500,
    "error": "Internal Server Error",
    "exception": "org.springframework.http.converter.HttpMessageNotWritableException",
    "message": "Could not write content: could not extract ResultSet (through reference chain: org.sklse.lab.bean.ResultModel[\"content\"]->org.hibernate.collection.internal.PersistentBag[0]->org.sklse.lab.bean.Student[\"submittedHomeworks\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not extract ResultSet (through reference chain: org.sklse.lab.bean.ResultModel[\"content\"]->org.hibernate.collection.internal.PersistentBag[0]->org.sklse.lab.bean.Student[\"submittedHomeworks\"])",
    "path": "/edu/guardian/children"
}

解决方案

一番debug之后很是头疼,后来请教了一位长者,指出可能是懒实例化的问题,于是查找到解决方案,在Spring Boot的application.properties配置项添加:

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

于是问题顺利解决

思考

在hibernate框架中,当我们要访问的数据量过大时,明显用缓存不太合适, 因为内存容量有限 ,为了减少并发量,减少系统资源的消耗,这时Hibernate用懒加载机制来弥补这种缺陷,但是这只是弥补而不是用了懒加载总体性能就提高了。

懒加载也被称为延迟加载,它在查询的时候不会立刻访问数据库,而是返回代理对象,当真正去使用对象的时候才会访问数据库。

这个例子当中的guardian.getStudents()是延迟加载的,最开始的studentList其实放的是 Hibernate 的 PersistentBag ,这个对象是不可以序列化的。

待补充具体原理

推荐阅读更多精彩内容