3

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

1) Entities 和 Value Objects (VOs) 之间似乎没有太大区别,并且当它们以任一方向通过服务层时,必须编写大量代码才能转换为另一个(Struts Actions 只处理VOs、DAOs 只处理实体)。因此,VO 和实体似乎有些多余。为什么两者都有?

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

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

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

5) VO 有一个字段作为其数据库 ID。我以为VO没有身份?这是怎么回事?

我希望这些问题足够笼统,足以引起人们的普遍兴趣。在这种类型的架构中,这似乎会一直出现。

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

4

3 回答 3

3

1.考虑DAO-VO转换;这是否有用取决于如何使用 Hibernate。如果整个 Web 请求处理在单个 Hibernate 会话中,则您实际上不需要单独的 VO。

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

简而言之,在您开始放弃这些 VO 之前,请仔细检查您的数据库事务和会话边界。

3.关于在Form中使用VO;如果 VO 很好地映射到 JSP,我会说为什么不呢?我要么对数据模型与它支持的过程如此紧密地匹配印象深刻,要么对数据库尚未标准化(这可能会也可能不会在未来造成问题)有点怀疑。

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

  1. 服务层必须具有知道要更改哪些数据库对象的工具,而 id 就是为此而设计的。服务层必须从数据库中检索 DAO 并将来自 VO 的字段写入 DAO 中,尽管它显然不需要用 VO 的 id 更新 DAO 的 id :)

  2. 您从请求中需要的是外键字段的 id。由于它来自客户端,您可能应该在业务逻辑中检查是否存在具有此类 id 的对象。

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

  • 设置 id,或
  • 使用服务层通过 id 将外来对象作为 VO 并将其放入您的 VO 中,并使用服务层将其存储

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

如果我正确地阅读了您的问题,您的 VO 通过 id 引用数据库中的其他对象。在这种情况下,您输入 id。如果你从客户端得到一个字符串,你应该在业务层(使用服务层)查找它,并将找到的对象的 id 放在 VO 中。或者,如果没有找到 ID,则返回一个体面的错误消息。

作为结束语;除非您知道自己在做什么,否则不要碰 DAO-VO。Hibernate 是一个强大而复杂的工具,看似简单易用。你很容易犯错误,而且很难找到。客户和老板们似乎都不喜欢在过去可以工作的东西中引入错误。

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

于 2008-10-03T20:58:03.513 回答
1

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

2)服务层:与DAO和Action层自然分离,对吧?

3) 只要在发送到 DAO 之前正确地验证了值对象,它就不会受到伤害

4)服务层应该负责两者之间的转换。在加载和节省时间期间

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

我希望这些简洁的答案有所帮助。我会尝试回来并稍后给出更长的答案。

于 2008-10-03T15:51:27.987 回答
0

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

例如,在我使用 Spring MVC 做的应用程序中,我有一个成员类。登录、注册、更改密码和编辑个人资料表单都绑定到这个类。该类还有一个休眠映射和一个很好的内部业务逻辑(例如,对于社交网络,一个“添加朋友”方法)。

于 2008-10-03T20:20:39.423 回答