简体   繁体   English

为什么加载惰性集合

[英]why the lazy collection is loaded

I have a Project entity with a oneToMany relationship with Event entity 我有一个与Event实体具有oneToMany关系的Project实体

public class Project {
   ....

   @OneToMany(mappedBy = "dossier", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
   private List<Event> events;

}

I have a ProjectService class 我有一个ProjectService类

@Service
@Transactional
public class ProjectService {

    public List<Project> findAll() {
        return (List<Project>) projectRepository.findAll();
    }
}

And a ProjectController 还有一个ProjectController

@RestController
@RequestMapping(value = "/projects")
public class ProjectController {

    @RequestMapping(method= RequestMethod.GET)
    public List<Project> getAllProject() {
        return projectService.findAll();
    }
}

In my client code I saw that the events of the projects are loaded and I don't understand why. 在我的客户端代码中,我看到项目的事件已加载,我不明白为什么。

I expected that at the end of the transaction of the method findAll in DossierService, the entities will be detached. 我预计在DossierService中方法findAll的事务结束时,实体将被分离。 Obviously my entities are still attached as the events are retrieved during the jackson serialization in my controller. 显然,我的实体仍然附着,因为在我的控制器中的jackson序列化期间检索了事件。

Project.events is by default lazy-loaded because it is a OneToMany relationship. Project.events默认是延迟加载的,因为它是OneToMany关系。

It does not mean that Project.events is not loaded. 这并不意味着没有加载Project.events It means that it will be loaded as soon as Project.getEvents() is called. 这意味着一旦调用Project.getEvents()就会加载它。

This occurs at the JSON serialization (when ProjectController.getAllProject() returns its response). 这发生在JSON序列化(当ProjectController.getAllProject()返回其响应时)。

In order to prevent that, there are 2 ways : 为了防止这种情况,有两种方法:

  • Either you explicitly call project.setEvents(null) (or an empty list) on every project returned by ProjectService . 您可以在ProjectService返回的每个项目上显式调用project.setEvents(null) (或空列表)。
  • Or you add a @JsonIgnore annotation on Project.events . 或者在Project.events上添加@JsonIgnore注释。

EDIT : if you are using spring-boot, an OpenEntityManagerInViewInterceptor is registered by default : 编辑 :如果您使用spring-boot,默认情况下会注册OpenEntityManagerInViewInterceptor

Spring web request interceptor that binds a JPA EntityManager to the thread for the entire processing of the request. Spring Web请求拦截器,它将JPA EntityManager绑定到线程以进行整个请求处理。 Intended for the "Open EntityManager in View" pattern, ie to allow for lazy loading in web views despite the original transactions already being completed. 用于“Open EntityManager in View”模式,即允许在Web视图中进行延迟加载,尽管原始事务已经完成。

You can disable this behavior by adding this line to application.properties : 您可以通过将此行添加到application.properties来禁用此行为:

spring.jpa.open-in-view=false

With this configuration, calling the getter outside of the hibernate session will cause a LazyInitializationException . 使用此配置,在hibernate会话之外调用getter将导致LazyInitializationException

There are two possibilities: 有两种可能性:

  1. An OpenSessionInView or OpenEntityManagerInView bean has been defined. 已定义OpenSessionInViewOpenEntityManagerInView bean。 This type of bean causes the Session or EntityManager , respectively, to be opened at the time the controller is invoked and remains open until the controller's body has been serialized. 这种类型的bean分别导致SessionEntityManager在调用控制器时打开,并保持打开状态直到控制器的主体被序列化。

    It is typically considered acceptable behavior in demo/small applications, but it's highly frowned upon in larger more complex applications as your queries should return fully initialized entities required for your view, controller, or logic. 它通常被认为是演示/小型应用程序中可接受的行为,但它在大型更复杂的应用程序中非常不受欢迎,因为您的查询应返回视图,控制器或逻辑所需的完全初始化实体。

  2. The JSON library has a hibernate addon enabled where it is capable of reattaching and hydrating the entity during the serialization process. JSON库启用了一个hibernate插件,它能够在序列化过程中重新附加和保护实体。

Otherwise, the default behavior that you expect where the Session / EntityManager has closed and the entity is detached once it's returned by the service is accurate. 否则,您希望Session / EntityManager关闭并且实体在服务返回后分离的默认行为是准确的。 The expected behavior would be a LazyInitializationException otherwise. 否则,预期的行为将是LazyInitializationException

Your entities are still attached until: 您的实体仍然附着,直到:

  • You ask the entity manager to clear the persistence context using entityManager.clear() 您要求实体管理器使用entityManager.clear()清除持久性上下文
  • You ask the entity manager to detach your entity using entityManager.detach(project) for every project. 您要求实体经理使用entityManager.detach(项目)为每个项目分离您的实体。

But if you know that your events will be loaded most of the time, you should then consider using FetchType.EAGER so that everything would be fetched at once. 但是如果您知道您的事件将在大多数时间加载,那么您应该考虑使用FetchType.EAGER,以便一次性获取所有内容。

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

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