簡體   English   中英

Hibernate Envers:初始化 Envers 代理

[英]Hibernate Envers: Initializing Envers Proxies

在 Hibernate Envers 中,一個實體的所有相關集合都被延遲加載,而不管設置的獲取類型是什么。 因此,當對具有其他實體集合(當然都經過審計)的實體進行審計查詢時,該集合首先是一個SetProxy (在調試時可以看到)。

那么,我如何初始化該代理? 使用Hibernate.initialize()沒有效果(我懷疑是因為 Hibernate 和 Envers 使用不同的代理對象)。 我知道我可以通過迭代它的項目來初始化集合,但這對我來說不是一個選擇,因為我在一個實體中有多個集合,更不用說維護問題了。

我需要急切地初始化它們,因為我是在稍后 Hibernate 會話已經關閉(將域對象轉換為 dtos)時訪問集合。

我正在使用 Hibernate 3.5.6。

顯然,這是 Hibernate Envers 的一個懸而未決的問題。 他們的 JIRA 中已經存在一個問題: https : //hibernate.atlassian.net/browse/HHH-3552 隨意投票,也許它會加快速度,當他們看到有些人希望修復此問題時;)

在 Envers 團隊解決這個問題之前,有一種解決方法對我有用:在集合上調用size()初始化代理對象。

到目前為止,我發現初始化 Envers 代理的最佳解決方法是使用Dozer 將 Envers 返回的審計實體映射到自身強制初始化。

例如:

    // Assuming you have an initialized EntityManager in entityManager & 
    // id contains your entity id..

    List<Object[]> auditList = (List<Object[]>)AuditReaderFactory.
                                   get(entityManager).
                                   createQuery().
                                   forRevisionsOfEntity(Foo.class, false, true).
                                   add(AuditEntity.id().eq(id)).
                                   getResultList();

    // Use a singleton in production apps instead...
    DozerBeanMapper mapper = new DozerBeanMapper();

    for(Object[] audit : auditList) {
        audit[0] = mapper.map(audit[0], Foo.class);
    }

    // The proxies in the Foo instances in auditList are now initialized

我對這個解決方案不是很滿意,但我更喜歡它而不是通過手動觸摸集合來初始化代理。 希望有人提出更好的替代方案,否則 HHH-3552 會得到修復!

你的設計有問題。

如果您需要初始化它們的攔截器內(我懷疑Envers通過攔截休眠呼叫),這意味着你需要了解你的域模型事先。 審計應該完全獨立於領域建模。

話雖如此,您可以使用一些通用反射方法來滾動您自己的初始化程序來迭代集合,或者您可以使用Open-Session-In-View模式並將其調整為與 Envers 一起使用(即,在您的攔截器內部)。

請記住,訪問這些項目可能會觸發其他查詢,如果您分析日志,這可能會造成混淆。


編輯:似乎 hibernate 具有提取配置文件,可以讓您在運行時選擇提取計划。 請參閱此SO 問題文檔

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM