likes
comments
collection
share

原创 | 使用 JPA 实现 DDD 持久化 -O/R 阻抗失配 (1/2)

作者站长头像
站长
· 阅读数 42

原创 | 使用 JPA 实现 DDD 持久化 -O/R 阻抗失配 (1/2)

原创 | 使用 JPA 实现 DDD 持久化 -O/R 阻抗失配 (1/2)

在使用面向对象的编程语言编写的应用程序中,对象是其基础构建块。由于前文表述的种种原因,我们需要将领域对象的状态持久化到某种存储媒体中,以便在需要时能够重建这些对象。通常而言,是将领域对象状态(值和关联)持久化到关系数据库中。

在以关系数据库为目标的持久化中,我们会尽量:

  • 将领域对象中的实体类与数据库中的表一一对应
  • 将实体实例与表中的记录(行)一一对应
  • 将实体实例属性与表中的字段(列)一一对应
  • 将实体类的标识属性对应到表中的主键字段

但是,对象模型(O)和关系模型(R)是基于不同的理论,针对不同的目标建立的,两者之间并不能那么完美匹配。实际上,两者在很多方面存在“阻抗失配(Impedance Mismatch)”。主要体现在以下的方面。

1. 粒度问题

我们知道,在领域模型中,有些实体持有值对象,这些值对象本身可能有多个属性。有时候,值对象内部甚至还包含下一级的值对象。类的粒度从粗到细:实体-值对象-简单属性,可以有3个甚至3个以上的粒度层次。

例如在电商网站中,顾客类Customer持有配送地址shippingAddress这样一个Address类型的值对象属性。

原创 | 使用 JPA 实现 DDD 持久化 -O/R 阻抗失配 (1/2)

而关系数据库中只有两种粒度:由你创建的关系类型(表),以及内置的数据类型,如VARCHARBIGINTTIMESTAMP等。它不能直接对应到对象模型中的多级粒度。尽管各种数据库系统往往允许用户创建自定义类型,但是操作起来很复杂,更关键的是:不同数据库系统的自定义数据类型不可移植。

2. 标识问题

在应用程序和数据库中,常常需要判断两个对象或者两行数据是不是相同的(代表相同的对象或数据行),就是通过什么样的标识来识别两个事物是不是相同的事物。

Java中,有两种不同的相等性概念:

  • 实例标识:大致等同于对象的内存位置,使用a == b进行检查。
  • 实例等价性:通过equals()方法的实现进行判断。

另一方面,数据行的标识会体现为主键值的比较。同一个表中主键值相同两个数据行代表同一行数据。

Java中有几个不相等的对象实例同时对应数据库同一行的情况很常见,例如在并发的应用程序线程中就是如此。

3. 继承与多态问题

面向对象有三大特征:封装、继承和多态。Java作为面向对象的编程语言,可以使用基类和子类来实现类型继承。在领域模型中,类型继承是非常常见的。例如银行系统的领域模型:

原创 | 使用 JPA 实现 DDD 持久化 -O/R 阻抗失配 (1/2)

银行账户Account这个超类有储蓄账户SavingsAccount和信用账户CreditAccount两种子类型。在超类Account中可以定义所有子类的共同属性(锁定状态locked、当前余额balance等),同时每个子类还可以分别定义自己特有的属性(例如信用账户CreditAccount子类拥有一个特有属性:信用额度creditLimit)。

Account抽象超类有一个owner(账户持有人)属性,指向另一个抽象基类Customer(客户)。Customer有两个具体子类:公司客户CompanyCustomer和个人客户PersonalCustomer。两个子类分别拥有自己的一批专有属性。

子类除了可以添加自己特有的属性之外,还可以添加方法、重写或实现超类的方法。例如超类Account上定义了抽象方法credit(),两个子类分别为这个方法提供自己的实现。

基于上面的分析,持久化必须:

  • 允许进行多态关联。

    例如上面的例子,某个Account实体实例account1owner属性可能关联的是一个CompanyCustomer,而另一个Account实体实例account2owner属性可能关联的是一个PeronalCustomer。持久化必须能够记录关联的具体子类型信息,以便在检索数据库重建Account实例的时候恢复正确的子类型关联。

  • 允许进行多态查询。

    例如上面的例子。当我们以具体子类为目标进行查询的时候,期望返回的是符合条件的某个子类的实例的集合。而当我们以基类为目标进行查询的时候,期望返回的是符合条件的所有子类型的实例的集合。

关系数据库中没有任何与数据继承和多态相关的概念。表之间没有继承关系,SQL也不提供任何多态查询的功能。

详细内容请戳这里↓↓↓

原创 | 使用JPA实现DDD持久化-O/R阻抗失配(1/2)

这一节就讲到这里,下一节我们讲**"O/R阻抗失配第2部分"**

如果觉得有收获,点个【赞】鼓励一下呗!

原创 | 使用 JPA 实现 DDD 持久化 -O/R 阻抗失配 (1/2)

转载自:https://juejin.cn/post/6865138398735269902
评论
请登录