如何正确使用Struts ActionForms,Value Objects和Entities?

时间:2008-10-03 14:27:07

标签: java design-patterns architecture oop

我继承了一个使用Struts,Spring和Hibernate的大型Java应用程序。我每天处理的类和接口是:Struts动作,Struts ActionForms,值对象,服务接口和实现,DAO接口和实现,以及实体。我很清楚大多数这些的方法和原因,除了我不确定ActionForms,Value Objects和Entities之间的职责分离是否正确。我还应该提到域模型(即所有实体)不包含太多(如果有的话)实际业务逻辑。这本质上是一个CRUD应用程序,大部分真正的逻辑都在数据库中(哎呀!)。无论如何,我想知道几个与Java有关的不同问题:

1)似乎实体和值对象(VO)之间没有太大区别,并且当它们在任一方向上通过服务层时,必须编写许多代码以转换到另一个代码中(Struts Actions)只处理VO,DAO只处理实体)。因此,VO和实体似乎有些多余。为什么他们俩都这样?

2)VO< - >实体翻译代码应该在哪里?服务层,实体,VO?

3)VO直接放入ActionForms并直接绑定到JSP中的标签(例如)。这是一个好习惯吗?如果没有,那么适当的设计是什么?

4)目前还不清楚如何在Value Objects中正确处理外键依赖关系。例如,某些VO具有类型字段,在数据库术语中,该字段表示类型表中的外键关系。在UI中,这会转换为允许用户选择类型的下拉字段,或者只显示该类型的文本表示的标签(取决于它所在的屏幕)。现在,VO是否应该具有类型ID,类型的文本表示或两者的属性?谁负责在两者之间进行翻译?何时?

5)VO有一个数据库ID字段。我以为VO没有身份?怎么了?

我希望这些问题足够通用,能引起普遍关注。在这种类型的架构中,似乎会出现这种情况。

另外,我怀疑这个架构对于这个应用程序来说很重要,如果你有一个更好的建议,请继续。但我主要对上述问题的答案感兴趣,因为不同的架构是我现在无法做的长期重构。

3 个答案:

答案 0 :(得分:3)

1。 考虑DAO - VO转换;这是否有用取决于Hibernate的使用方式。如果整个Web请求处理都在一个Hibernate会话中,那么您不应该真正需要单独的VO。

但是,如果DAO层打开会话以检索对象并在使用DAO之前关闭会话,则可能会遇到集合和对其他对象的引用的问题。那些延迟加载的可能性很大,这意味着在请求这些属性时仍然必须打开Session。

简而言之,在您开始放弃之前,这些VO会很好地,严格地看待您的数据库事务和会话边界。

3。 至于在表格中使用VO;如果VO很好地映射到JSP,我会说为什么不呢?令我印象深刻的是,数据模型与它支持的过程非常匹配,并且有点怀疑数据库尚未规范化(未来可能会或可能不会产生问题)。

返回1.如果您使用延迟加载和集合的DAO,请记住数据库会话还必须包含JSP阶段,因为在该阶段将读取DAO。

  1. 服务层必须具备知道要更改哪些数据库对象的工具,并且id旨在实现这一目标。服务层必须从数据库中检索DAO并从DAO中的VO中写入字段,尽管它显然不需要使用VO的id来更新DAO的id:)

  2. 请求中您需要的是外键字段的ID。因为它来自客户端,您应该检查业务逻辑是否存在具有此ID的对象。

  3. 根据VO是接受外来对象的id还是需要一个对象,您应该:

    • 设置ID或
    • 使用服务层和id通过id获取外来对象作为VO 将它放在您的VO中,并使用服务层
    • 存储它

    您的业务层负责翻译,因为服务层仅处理对象检索和存储。并且text或id不是对象而是对象的标识符。服务层可以 提供搜索工具,但不应该需要上下文信息。

    如果我正确地阅读了您的问题,您的VO会通过id引用数据库中的其他对象。在这种情况下,您输入ID。如果从客户端获取String,则应在业务层(使用服务层)中查找它,并将找到的对象的id放在VO中。或者,如果未找到ID,则返回正确的错误消息。

    作为结束语;不要触摸DAO-VO的东西,除非你知道你在做什么真的很好。 Hibernate是一个功能强大且复杂的工具,看起来很容易使用。你很容易犯错误,很难找到。客户和老板们似乎都不喜欢过去工作的东西中引入的错误。

    顺便说一下;我在DAO-VO中的保守主义来自修复由于EJB2到Hibernate转换中的类似问题而导致的问题。魔鬼在细节中,改变你处理数据层的方式是一个重要的重构,即使它看起来像小菜一碟。

答案 1 :(得分:1)

1)不需要单独的VO和实体:一些公司为其项目强制要求这样的结构。它可能在一个不同的项目中是有意义的,因此它是强制性的(我只能猜测)

2)服务层:它是与DAO和Action层的自然分离,对吗?

3)它不会伤害值但是只要在发送到DAO之前对对象进行了适当的验证,对象就会被绑定

4)服务层应负责在两者之间进行翻译。在加载和节省时间

5)如果他们没有身份,那么你将如何防止重复?

我希望这些简洁的答案有所帮助。我会尽力回来再给你一个更长的答案。

答案 2 :(得分:0)

要回答你的最后一部分,请使用Spring MVC而不是Struts。然后你可以在所有层使用相同的域对象 - 绑定到表单参数的类也在Hibernate中使用,并包含真正的业务逻辑。

例如,在我使用Spring MVC的应用程序中,我有一个成员类。登录,注册,更改密码和编辑配置文件表单都绑定到此类。该类还具有hibernate映射和内部的一些业务逻辑(例如,对于社交网络和“添加朋友”方法)。