簡體   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