2010-01-21 63 views
0

我目前正在實現一個grails web應用程序,它有一些複雜的表單,其中關聯圖上的修改應該在「內存中」(即http會話)因爲實體或頂級域對象沒有保存。在Grails應用程序中管理多個請求中的關聯

例如

頂部至底部:文檔 - >類別 - >子類別...

要求:修改記錄/類別/子類別只應每當保存文檔並保存在任何其他情況。

我的第一種方法是存儲在HTTP會話的關聯ID,但這個結束了,在我的DocumentController.update動作很多線索代碼與當前持久狀態

// update some abstract association 
for (def Iterator it = documentInstance.association.iterator(); it.hasNext();) { 
    if (!session.association.contains(it.next().someEntity.id)) { 
    it.remove() 
    } 
} 

for (def roleTypeId in session.association) { 
    // add/update association 
    ... 
} 

線索同步會話狀態代碼在實際修改數據時變得更糟,例如,這意味着修改後的類別對象在頂級實體保存時必須被分離/重新連接/合併。

我會對你對這種長期工作單元的想法非常感興趣。

回答

0

一些想法:

把你的代碼從控制器中分離出來並放入服務中。

將服務的靜態'transactional'屬性設置爲false,並控制該事務。它可能看起來有點像這樣:

class DocumentService { 
    // take control from spring 
    static transactional = false 

    void updateMethod() { 
     Document.withTransaction { transact -> 
      // handle your business 

      // problems? - you can always rollback without breaking anything 
      transact.setRollbackOnly() 
     } 
    } 
} 

這將允許您使用'def documentService'行將服務注入到控制器中。您可以處理服務中的所有邏輯並更全面地測試所有內容。

+0

thx爲您的答覆。事實上,這已經是它在我的DocumentController.update行動 我已經嘗試的方式是分離整體對象圖,但這導致了與髒對象集合的問題,合併... 你做過嗎在你的Grails應用中有類似的用例嗎?如果是的話,你是如何實現修改關聯並保持對多個請求的修改而不是立即保存修改的? – 2010-01-21 12:32:33

+0

我還沒有處理類似的用例 - 所以我不確定這是否正確。但我會使用服務作爲流程的一部分。看起來管理你正在談論的最好方法是使用稱爲範圍的另一個靜態屬性將服務範圍擴展到流程。將範圍設置爲'流'或'對話'(以包含子流)並記住在您的服務類中實現Serializable。然後,您應該能夠在這些範圍內管理您的更改,而不必擔心個別請求。 – Brandon 2010-01-21 13:11:14

2

您可以使用會話每會話模式a.k.a.「長談話」。嘗試使用這種方式的Grails Webflow插件,或者如果您認爲Webflow不適合您的需求,則可以自己實施會話每對話。

基本前提是,在開始對話時,您打開一個新的hibernate會話(使用flush mode = manual)並將其存儲在用戶的http會話中。在每個後續http請求的開始處,您需要確保sessionFactory.getCurrentSession返回對話的hibernate會話,並且記得在每個請求結束時斷開此會話以關閉請求之間的jdbc連接。當您到達對話結束時,您會刷新會話以保留所有更改,或關閉而不清除以取消它們。

hibernate網站/ Java Persistence with Hibernate book有一些關於如何做到這一點的非常好的信息,但除了webflow之外,在grails中沒有開箱即用的支持。我正在編寫一個SessionPerConversation插件,但這已經很早了。我的方法是查看grails 1.2.0源代碼並複製它們如何實現.withNewSession,然後用.withConversation,.endConversation和.discardConversation方法修飾我的控制器。當我有更進一步,我可能會張貼一些代碼State Your Bizness

我到目前爲止遇到的陷阱是...

  1. 如果用戶永遠不會結束,他們的談話休眠會議將保持開放(雖然不是JDBC連接),直到他們的HTTP會話超時。如果您支持多個對話,則每個用戶可能有多個會話會話,對於高用量的會話,您可能會遇到內存問題。

  2. 您必須小心自動會話沖洗。當您根據您使用的id生成策略, 或您的主叫交易服務 新增實體時,可能會發生這種情況。

+0

廣告1.)是不是有可能序列化休眠會話(我猜領域類必須是可序列化的),並將數據放入隱藏字段? HTTP會話的內存消耗會減少,雖然... 廣告2.)我認爲使用適當的刷新模式將禁用自動會話刷新,即使使用交易服務等。 – 2010-01-27 14:24:00

+0

1. Hibernate的會話是可序列化的,所以你可能會這樣做,但是你需要提交序列化的會話來處理會話中發生的任何請求 - 包括導航和重定向。對於這種情況,將hibernate會話與conversationId相關聯並將conversationId作爲請求參數傳遞會更方便。有趣的想法雖然 2.看起來你是對的。我誤解了grails webflow文檔(如果你想將它們存儲在流/會話範圍中,你必須將服務標記爲非事務性的)。 – cressie176 2010-01-28 08:00:00

+0

我喜歡這種方式 - 我將實現它(不知道隱藏的領域,但文件序列化就足夠了),然後發佈我的結果... – 2010-01-28 12:27:07

相關問題