2010-01-21 57 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

相关问题