繁体   English   中英

为什么加载惰性集合

[英]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

有两种可能性:

  1. 已定义OpenSessionInViewOpenEntityManagerInView bean。 这种类型的bean分别导致SessionEntityManager在调用控制器时打开,并保持打开状态直到控制器的主体被序列化。

    它通常被认为是演示/小型应用程序中可接受的行为,但它在大型更复杂的应用程序中非常不受欢迎,因为您的查询应返回视图,控制器或逻辑所需的完全初始化实体。

  2. JSON库启用了一个hibernate插件,它能够在序列化过程中重新附加和保护实体。

否则,您希望Session / EntityManager关闭并且实体在服务返回后分离的默认行为是准确的。 否则,预期的行为将是LazyInitializationException

您的实体仍然附着,直到:

  • 您要求实体管理器使用entityManager.clear()清除持久性上下文
  • 您要求实体经理使用entityManager.detach(项目)为每个项目分离您的实体。

但是如果您知道您的事件将在大多数时间加载,那么您应该考虑使用FetchType.EAGER,以便一次性获取所有内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM