【问题标题】:Mapping database tables to Java classes - Dependencies将数据库表映射到 Java 类 - 依赖项
【发布时间】:2016-10-04 00:25:59
【问题描述】:

我试图将数据库表表示为 Java 对象。我不想使用 JPA 或 Hibernate。我使用 JDBC 来实际连接数据库。

目前我有三个表:

  • 具有 Id(主键)、唯一电子邮件和配置文件 ID(配置文件表的外键)的用户

  • 一个配置文件,其中包含一个 Id(主键)、一些附加字符串、一个用户 ID(用户表的外键)和一个联系人 ID(联系人表的外键)

  • 一个联系人,它有一些字符串列、一个 Id(主键)和一个所有者 ID(用户表的外键)

现在我的 User 类看起来像这样:

public class User {
    private Integer id;
    private String email;

    private Profile profile;
}

我的 Profile 类如下所示:

public class Profile {
    private Integer id;

    private User owner;

    private Contact contact;

    private String picturePath;
    private String hobbys;
    private String job;
}

最后是 Contact 类:

public class Contact {
    private Integer id;

    private User owner;

    private String firstName;
    private String middleName;
    private String lastName;
}

所以我打算为每个类写一个Dao,它为数据库请求提供不同的方法,做请求并相应地返回对象。
我认为在每个 Dao 中都有一个检索完整对象的函数会很好。这意味着,对于 UserDao,它返回一个用户,其中填充了 id 和电子邮件,并且 Profile 对象也是从数据库中的相应值创建的。因此,此 Profile 对象中的联系人也将从数据库中相应的联系人条目中填充。

我现在遇到的问题是如何组织这个,因为对于用户我必须要求 ProfileDao 创建一个 Profile 对象,而在 ProfileDao 中我需要向 ContactDao 询问相应的联系人。 ContactDao 通常也会尝试获取用户,因为需要完全创建 Contact 对象。
所以我需要以某种方式告诉 Daos 只检索对象本身而不是链接的对象。
但这对我来说似乎很奇怪。

这真的是正确的方法吗?就像使用附加参数调用 ContactDao 一样,该参数告诉 Dao 仅获得平面表示。
或者我应该只通过用户的 id 将用户链接到联系人,并提供在需要时检索相应用户的功能?

解决这个问题的正确方法是什么?

编辑 在我看来,我可能遗漏了一个重要信息(因为我不知道它可能很重要)。实际上@Oleg 的回答给了我这种洞察力。
我实际上在做的是:我构建了一个 SOAP Web 服务,它应该处理与数据库的所有连接,而且(显然)也处理整个内部逻辑。最重要的是,我想创建一个可以集成到网页或应用程序中的 SOAP 客户端。
我的想法是,我需要提供所有可能以任何我能想象的方式访问我的数据库中的数据。但@Oleg 的回答似乎暗示了别的东西:
如果我正在实现一个 SOAP-API(他的示例是 REST,但最后它并不重要),我应该只关心我需要的东西。
比如说如果我想拥有一个用户,我只需创建一个带有 ID 和电子邮件的用户对象。如果我想拥有该用户的个人资料,我会执行另一个请求,它会为我提供一个平面配置文件对象。然后我也会在我的 API 中只实现那些东西。
考虑到这些额外信息,这是正确的方法吗?

【问题讨论】:

  • 我会将用户传递给联系人。我会允许一个 NULL 用户。但是要回答关于“正确”方式的最后一个问题,我会使用 JPA,因为它已经完成了这些工作。为什么没有这个选项?
  • 嘿。谢谢。传递用户已经是比我传递布尔值来判断它应该检索平面还是深度表示的想法更好的解决方案。我宁愿不喜欢使用 JPA,因为我觉得我会将太多的控制权交给一个封装的框架。老实说,我不喜欢在后台发生这么多你无法控制的事情。
  • 嗯......如果该控件正在执行您想要的操作,那么我自己看不到任何问题。我以前也有你的感觉,但是在重新发明轮子数百次之后,你终于意识到你不需要这样做。

标签: java sql database postgresql data-binding


【解决方案1】:

我的建议是从以 EE 为中心的 DAO 概念转向领域驱动的设计。将 DAO 接口(如果您走这条路,请不要定义类)定义为某种 Java 实体到 DB 表的映射,然后在不同的业务流中使用此类 DAO 的集合,这种做法被广泛传播。缺陷在于您的业务代码与 DAO 紧密耦合,并且您有类似您所问的问题,因为您想为没有通用用例的事物提供“通用”解决方案。

相反,定义另一种类型的数据 API,它由您的业务域流驱动并且仅用于该特定流或业务域。将其视为业务流程在不同步骤所需数据的高级 API,因此使用高级输入和高级输出而不是直接的 DB 映射来实现它。想象一下,您正在定义一个 REST API,您将为 外部 用户提供哪种类型的请求和响应来操作数据,禁止该接口级别的任何内部知识。

这样做你会的

  1. 解耦不同的业务逻辑领域;
  2. 提供小型可测试 API(接口)以覆盖每个业务流程
  3. 将不再控制这些DAO 函数到底是什么——两年前有人投入其中以及他们在哪里使用
  4. 将能够迁移到不同的数据库技术(我的意思不是从例如 Oracle 到 MSSQL,而是到例如 No-SQL 解决方案,如果您决定要一个)
  5. 最终会有一个其他人可以理解的设计

【讨论】:

  • 嘿,谢谢。我想你的回答给了我一些思考。我相应地编辑了我的问题。
【解决方案2】:

“老实说,如果后台发生了很多你无法控制的事情,我真的不喜欢它”——JPA 解决了你的问题,它是一个行业范围内经过实战验证的 API,有几个很好的实现。 EclipseLink 是参考实现,根据我的经验,Hibernate 更多产,它们都可以满足您的需求。它还将为您处理事务方面的事情。为了回应您的担忧,我想不出任何您无法控制的事情。

我的意见是,既然有该领域的专家编写的免费库,为什么还要维护和测试您自己的代码来做每个 Java 开发人员都在做的事情?

【讨论】:

  • 我已经经历过多次退出 Hibernate 的痛苦。一切都很痛苦,在所有情况下,最终结果都更小、更清晰、更容易理解、更不容易出错且更快。在某些情况下,Hibernate 和 Co 是有益的,我仍然需要看到一个。对于大多数实际情况,根据领域模型划分代码并保持简单,以及数据访问的高级抽象,将在提供清晰性和可扩展性的同时,在中长期维护方面节省大量成本。跨度>
  • 在这种情况下,我可以加入@Oleg。 Hibernate 搞砸了项目,让你(在我看来)对访问数据库等的控制更少。
猜你喜欢
  • 2014-06-24
  • 2013-02-16
  • 1970-01-01
  • 1970-01-01
  • 2012-10-08
  • 2013-03-17
  • 1970-01-01
  • 1970-01-01
  • 2012-06-02
相关资源
最近更新 更多