[英]why the lazy collection is loaded
我有一个与Event实体具有oneToMany关系的Project实体
public class Project {
....
@OneToMany(mappedBy = "dossier", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Event> events;
}
我有一个ProjectService类
@Service
@Transactional
public class ProjectService {
public List<Project> findAll() {
return (List<Project>) projectRepository.findAll();
}
}
还有一个ProjectController
@RestController
@RequestMapping(value = "/projects")
public class ProjectController {
@RequestMapping(method= RequestMethod.GET)
public List<Project> getAllProject() {
return projectService.findAll();
}
}
在我的客户端代码中,我看到项目的事件已加载,我不明白为什么。
我预计在DossierService中方法findAll的事务结束时,实体将被分离。 显然,我的实体仍然附着,因为在我的控制器中的jackson序列化期间检索了事件。
Project.events
默认是延迟加载的,因为它是OneToMany
关系。
这并不意味着没有加载Project.events
。 这意味着一旦调用Project.getEvents()
就会加载它。
这发生在JSON序列化(当ProjectController.getAllProject()
返回其响应时)。
为了防止这种情况,有两种方法:
ProjectService
返回的每个项目上显式调用project.setEvents(null)
(或空列表)。 Project.events
上添加@JsonIgnore
注释。 编辑 :如果您使用spring-boot,默认情况下会注册OpenEntityManagerInViewInterceptor :
Spring Web请求拦截器,它将JPA EntityManager绑定到线程以进行整个请求处理。 用于“Open EntityManager in View”模式,即允许在Web视图中进行延迟加载,尽管原始事务已经完成。
您可以通过将此行添加到application.properties
来禁用此行为:
spring.jpa.open-in-view=false
使用此配置,在hibernate会话之外调用getter将导致LazyInitializationException
。
有两种可能性:
已定义OpenSessionInView
或OpenEntityManagerInView
bean。 这种类型的bean分别导致Session
或EntityManager
在调用控制器时打开,并保持打开状态直到控制器的主体被序列化。
它通常被认为是演示/小型应用程序中可接受的行为,但它在大型更复杂的应用程序中非常不受欢迎,因为您的查询应返回视图,控制器或逻辑所需的完全初始化实体。
JSON库启用了一个hibernate插件,它能够在序列化过程中重新附加和保护实体。
否则,您希望Session
/ EntityManager
关闭并且实体在服务返回后分离的默认行为是准确的。 否则,预期的行为将是LazyInitializationException
。
您的实体仍然附着,直到:
但是如果您知道您的事件将在大多数时间加载,那么您应该考虑使用FetchType.EAGER,以便一次性获取所有内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.