模型/实体类是否有模式

时间:2010-01-19 22:14:30

标签: java design-patterns model entity

从多个数据源中提取模型对象时,最佳方法是什么?

例如我有一个应用程序已经使用hibernate将一些数据存储在mySQL数据库中。如果我想在EC2或Google App Engine中存储其他一些对象,该怎么办?我理解DAO的摘要是使用特定数据源的实现,但实体本身呢?

起初我认为用jpa注释注释我的实体是一个很好的解决方案,但现在看来我真的把我的实体绑定到特定的实现。以App Engine为例,其中一些注释毫无意义。

似乎我需要一个纯粹的POJO类来表示我的实体,完全没有持久性逻辑。如果我想模仿一只狗(是跛脚的选择,但无论如何) 有一个抽象的Dog类是否有意义,然后定义子类以使用特定的持久性解决方案:HibernateDog,GAEDog等。

感谢。

6 个答案:

答案 0 :(得分:4)

这是一个很好的问题,即使这个问题不是新问题。作为一个行业,多年来我们一直在改变这个主题的“传统智慧”。你今天得到的答案不一定是你5年前或未来5年所得到的。

在描述如何处理这个项目时,我想知道你没有说过的一些事情:你的应用程序是Dog实体的“记录系统”吗?关于Dog实体需要了解的其他子系统/层/应用程序。

在Java中,当你编写像Animal这样的全新类型时,>狗,你获得以下奖励:有机会编写更多代码,知道如何与Animal对象和Dog对象进行交互。我在2010年不太相信这是一个好主意,而不是五年前。

您是否负责设计存储狗信息的数据库?我们过去常常这样做,但现在我经常发现自己整合了实际由其他系统管理的数据记录:谷歌API,LDAP实体,数据仓库,诸如peoplesoft等产品。

如果你负责定义Dog是什么以及它们如何与宇宙互动,我会看一种与域无关的方法来模拟内存中的Dog信息。有吨:XML / DOM,JSON,Map等。

以这些格式移动其他人的数据的好处很多......

  • 您不必编写POJO
  • 这些功能丰富,文档和测试
  • 有许多现有的API可用于转换,操作和序列化这些生物
  • 您可能会在其他域中重复使用您的视图/控制器/其他代码

另一方面......如果您是Dog数据的记录系统,请考虑使用接口而不是抽象类。或者可能是接口抽象类。 Java只有单继承;将您的视图/控制器/其他代码绑定到接口,以保证最大的未来灵活性。

答案 1 :(得分:2)

Hibernate的一个问题是它将自己的Collection实现注入到您的域类中,如果您尝试使用序列化(例如从服务器到客户端)通过线路发送您的类,则会导致问题。

在上面的示例中,我将质疑是否需要提供特定于存储的子类:

这些类是否真的应该包含与存储方式有关的状态?即,这是一个集体的核心概念,因此值得在继承中使用你的“一次性”(在Java中)?我认为在您的示例中更有用的继承层次结构将类似于:

  • 动物
    • 哺乳动物

此外,根据您提出的设计,如果您希望将Dog实例保存到Hibernate但不知道Dog是否为{{1},则可能会遇到问题}},HibernateDog等,此时必须执行检查/向下转换。

答案 2 :(得分:2)

JPA注释可以很好,因为它们允许您将对象关系映射(ORM)元数据放在与实体类相同的文件中,但是当您组合JPA元数据时,您完全可以理解这些问题。与“纯粹的”POJO。这是一种权衡。

然而,还有另一种选择。您可以在XML文件中外部化ORM配置,并以这种方式将这些详细信息保留在实体类之外。 JPA提供了XML配置语法,但对于我的项目,我更喜欢使用本机Hibernate XML映射来增加它们提供的灵活性。它可能不像基于注释的方法那么时髦,但根据我的经验,它的效果非常好。

答案 3 :(得分:2)

您正确使用DAO层从其他图层抽象数据源详细信息。因此,模型层实际上应该不知道正在使用哪种数据存储技术或数据库。

您的问题的答案是:使用服务层。这是您放置所有业务代码的层。要实例化哪个实体,使用哪个DAO,如何证实数据,事务划分等等。

因此,服务层应该支持加载/持久化您的实体。这就是你应该嵌入关于使用什么数据源/数据库的逻辑的地方。使用Spring的依赖注入来帮助你。将您选择的DAO,实体注入服务层。

实体类:狗,猫

服务类:AnimalCenterService

DAO课程:AnimalCenterHibernate,AnimalCenterJDBC

如果需要更多解释,请告诉我。 只差我2美分

答案 4 :(得分:1)

你所拥有的似乎是正确的方法。好的设计并不意味着实体不依赖于技术,只是意味着如果您更改技术,则更改应用的1层。

如果您使用JPA,使用JPA的实体是一个很好的解决方案。除了这些实体,您还可以拥有更多连接到GAE等的“实体”(POJO)

关于抽象的狗和子类,这似乎有点矫枉过正,除非你确实真的需要。如果您确实需要,请检查DTO对象:http://en.wikipedia.org/wiki/Data_transfer_object

DTO用于以一致的方式将对象传输到上层(在DAO之上)(并使其可序列化),即使在持久层中处理多个数据源/技术时也是如此。

答案 5 :(得分:1)

您不希望持久性特定代码继承自您的实体类,因为这样就无法对域实体类使用继承。例如,如果HibernateDog继承自Dog,则不允许Poodle从Dog继承而不强制Poodle特定于Hibernate。

一种有效的方法是使用特定于持久性的数据实体。您的域实体类将通过​​接口委托数据实体对象获取其持久属性。然后,只要它们符合您的数据实体接口,就可以替换不同的持久性实现特定数据实体类。

狗参考(和代表)DogEntity界面。 Poodle继承自Dog,PoodleEntity继承自DogEntity。

HibernateDog实现DogEntity
HibernatePoodle实现了PoodleEntity并继承自HibernateDog ...
StubDog实现了DogEntity
StubPoodle实现了PoodleEntity并继承自StubDog
......

您可以拥有任意数量的数据实体类型。数据实体非常精简,只能保存持久性成员变量和注释或持久性所需的其他代码。

域实体将包含特定于实体的业务逻辑。