目前正在使用JCR(Modeshape)进行测试应用。
抽象流程如下:session.open,存储库提取或多个与查询相关的节点session.close。
生成的节点包含我需要呈现给视图的属性等。我目前有一个简单的设置,让视图直接从jcrNode获取属性。但是,这会产生如下错误:“ID为'e2881d98-56fd-4a57-9cce-1a7d087a11e8'的会话已关闭”,这是有道理的。
我认为一般方法(如果不是这样,请更正)将创建某种nodeDTO,当会话仍处于活动状态时由jcrNode填充。然后视图可以随意使用nodeDTO。
现在,这种nodeDTO的完美结构将模仿jcrNode 1对1的结构,那么为什么不使用jcrNode作为DTO本身呢?这将通过类似于休眠分离/附加的东西来实现。我意识到jcrNode(及其子代)可以包含大量数据,因此应该有一些参数来确定分离的深度等。
另一种方法是使用openSessionInView模式,尽管这将是特定于mvc框架的。
所以我可以看到几种方法,首先是最好的方法(imo):
对“最佳实践”方法的任何评论等都非常感谢。
答案 0 :(得分:2)
不幸的是,JCR 2.0规范没有定义节点与会话分离的方法,因此这种功能将是特定于实现的。
代替JCR方法,唯一与JCR实现无关的技术是在您自己创建的非常简单的结构中复制属性和子引用。是的,该结构在高层次上与JCR节点非常相似,但它不需要在节点上定义90%的方法:一个简单的属性映射(按名称)和一个列表(或子节点的有序映射。通过这样做,您的代码将负责复制您感兴趣的节点和子图,因此您可以定义语义以满足您的需求。
但是,作为ModeShape的项目负责人,我同意分离JCR节点似乎是一个很好的功能,所以我在ModeShape项目中将其记录为enhancement request。在正确的语义方面(特别是与子节点或后代节点有关)有很多细节需要解决,所以我邀请您观看该请求并参与有关该问题的讨论。
答案 1 :(得分:0)
我一直在Modeshape-in-JBoss上开发JBoss Seam Web应用程序。起初我也使用了DTO方法,但放弃了。相反,对于Seam对话或整个Servlet会话,更容易保持JCR会话打开。
如果您没有使用Seam,那么您可以对Servlet请求范围使用类似的方法而不是对话。
我仍然处于初始开发阶段 - 而不是生产阶段 - 因此不能声称这是“最佳实践”。然而到目前为止,两者似乎都是可行的方法,我对它们没有任何问题。
首先,我有一个应用程序范围的Seam管理器组件(使用@Unwrap),它创建了用于login()的JCR存储库(使用ServiceLoader)。
然后是会议:
对话范围的JCR会话:我创建了一个转换范围的Seam管理器组件,它将JCR会话置于会话范围内。 Seam组件在创建时执行repository.login(),在对话结束时销毁组件时执行session.logout()。这与通常在Seam应用程序中使用的对话作用域JPA EntityManager基本相同。
会话范围的JCR会话:与上面相同,但在Seam(Servlet)会话范围中除外。这显然导致JCR会话开放的时间更长(可能是几小时)。我不知道是否有任何陷阱,但到目前为止,这似乎是更自然的方法。
在这两种情况下,应用程序代码都会在进行任何更新后执行session.save()。
但是,我确实同意某种无会话DTO实用程序API非常有用。如果您使用EJB向客户端公开JCR功能,这一点就变得很明显。由于EJB只能传递可序列化的数据对象,因此无法直接传递JCR节点和属性和值。我在开发Eclipse RCP应用程序(Web应用程序的伴侣)时遇到了这种情况,该应用程序需要访问在JBoss中运行的相同Modeshape存储库。我最终做了一些非常类似于Randall推荐的事情:开发简单的可序列化NodeDTO和PropertyDTO对象,然后使用一些实用工具方法从JCR节点和属性创建它们。如果Modeshape或JCR可以提供这些实用程序来帮助客户端 - 服务器访问存储库,那就太棒了!