个人主页: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本地运行的时候接口正常:
- 但是奇怪的是部署到服务器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 ,这个对象是不可以序列化的。
待补充具体原理
网友评论