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