简介
在过去 5 到 10 年中,开发人员对企业应用程序中的实体进行持久化的方式发生了根本性变化。早期的企业应用程序使用数据库表和 表之间的外键关系进行实体建模。应用程序被看作查看和查询数据库底层模型的方式。近几年,数据库中的实体建模逐渐向应用程序对象 模型中的实体建模转变。现在大家已经意识到,数据库仅仅是存储对象结构所定义的持久化信息的一种机制。把建模从数据库转移到对象 模型中有许多优点,包括:
持久化实体与对它们执行的操作更紧密地集成
有助于创建松散耦合的应用程序组件
与关系数据库相比,面向对象模型支持更丰富的关系
更加独立于特定的数据库平台
发生这种转变的主要原因是出现了功能强大的对象-关系映射(ORM)系统,它们支持按照与目标语言的习惯用法一致的方式访问持久化 对象。Hibernate 和 TopLink 等工具大大简化了把对象模型映射到关系数据库模式的过程。
自从这些工具出现以来,使用它们的方法也有所变化。最初,许多开发人员按照使用数据库表的方式使用 ORM 工具。实体一对一地映 射到数据库表。对应于主键等字段的变量在各个实体中重复出现。因为数据库不支持与实体相关联的行为,领域模型最终只具有简单的变 量以及相关的 getter 和 setter 方法。这些实体的行为最终由服务或视图层实现。
在许多项目中使用 ORM 工具的经验揭示了处理这些问题的更好方法。业务领域各不相同,所以它们的领域模型和持久化方式也可能不 同,但也有相同之处。本文讨论应用于不同行业的许多领域模型的最佳实践。这里提供的最佳实践有助于产生更加一致、可重用且可维护 的领域模型。我们使用 Hibernate 演示这些最佳实践,但是许多概念可以应用于其他 ORM 工具。
本文分为两部分。第 1 部分讨论以下方面的一些基本概念:
实现领域中的通用功能
减少数据访问层中的 代码重复
按照一致的方式处理对实体修改的审计
第 2 部分 更深入地讨论这里介绍的一些概念,还要讨论领域模 型中的性能调优。
从基础开始:对象模型
定义一个支持持久化对象的对象模型的过程与定义任何对象模型相同 。首先,寻找所有对象共享的通用元素。持久化信息中有两个通用元素:惟一地标识持久化对象的方法(应该能够跨应用程序的各次执行 标识对象),以及关于对象实例的审计信息。图 1 说明如何用接口和基类定义这两个概念:
图 1. 通用的接口和基类
图 1 引入了 Identifiable 和 Auditable 接 口,这些接口定义的 API 用来标识对象实例和设置对象实例的审计信息。还引入了 BaseEntity 和 AuditableEntity 基类,可以根据是 否需要对象的审计信息,分别从这些基类派生出具体的持久化类。
通过用这些接口定义持久化对象,就可能创建出可以应用 于所有具体对象类型的抽象行为。这包括 UI 层(用来标识要执行创建、读取、更新和删除(CRUD)操作的对象)以及服务和数据层。本 文的代码示例(在 下载 中可以获得完整的代码包)演示如何使用这些接口帮助执行审计和减少数据访问对象(DAO)中的代码重复。