持久化模式,第 1 部分:现代 ORM 工具的策略和最佳实践

在过去 5 到 10 年中,开发人员对企业应用程序中的实体进行持久化的方式发生了根本性变化。早期的企业应用程序使用数据库表和表之间的外键关系进行实体建模。应用程序被看 作查看和查询数据库底层模型的方式。近几年,数据库中的实体建模逐渐向应用程序对象模型中的实体建模转变。现在大家已经意识到,数据库仅仅是存储对象结构 所定义的持久化信息的一种机制。把建模从数据库转移到对象模型中有许多优点,包括:

  • 持久化实体与对它们执行的操作更紧密地集成
  • 有助于创建松散耦合的应用程序组件
  • 与关系数据库相比,面向对象模型支持更丰富的关系
  • 更加独立于特定的数据库平台

发生这种转变的主要原因是出现了功能强大的对象-关系映射(ORM)系统,它们支持按照与目标语言的习惯用法一致的方式访问持久化对象。Hibernate 和 TopLink 等工具大大简化了把对象模型映射到关系数据库模式的过程。

自 从这些工具出现以来,使用它们的方法也有所变化。最初,许多开发人员按照使用数据库表的方式使用 ORM 工具。实体一对一地映射到数据库表。对应于主键等字段的变量在各个实体中重复出现。因为数据库不支持与实体相关联的行为,领域模型最终只具有简单的变量以 及相关的 getter 和 setter 方法。这些实体的行为最终由服务或视图层实现。

在许多项目中 使用 ORM 工具的经验揭示了处理这些问题的更好方法。业务领域各不相同,所以它们的领域模型和持久化方式也可能不同,但也有相同之处。本文讨论应用于不同行业的许多 领域模型的最佳实践。这里提供的最佳实践有助于产生更加一致、可重用且可维护的领域模型。我们使用 Hibernate 演示这些最佳实践,但是许多概念可以应用于其他 ORM 工具。

本文分为两部分。第 1 部分讨论以下方面的一些基本概念:

  • 实现领域中的通用功能
  • 减少数据访问层中的代码重复
  • 按照一致的方式处理对实体修改的审计

第 2 部分 更深入地讨论这里介绍的一些概念,还要讨论领域模型中的性能调优。





回页首


从基础开始:对象模型

定义一个支持持久化对象的对象模型的过程与定义任何对象模型相同。首先,寻找所有对象 共享的通用元素。持久化信息中有两个通用元素:惟一地标识持久化对象的方法(应该能够跨应用程序的各次执行标识对象),以及关于对象实例的审计信息。图 1 说明如何用接口和基类定义这两个概念:


图 1. 通用的接口和基类
通用的接口和基类

图 1 引入了 IdentifiableAuditable 接口,这些接口定义的 API 用来标识对象实例和设置对象实例的审计信息。还引入了 BaseEntityAuditableEntity 基类,可以根据是否需要对象的审计信息,分别从这些基类派生出具体的持久化类。

通过用这些接口定义持久化对象,就可能创建出可以应用于所有具体对象类型的抽象行为。这包括 UI 层(用来标识要执行创建、读取、更新和删除(CRUD)操作的对象)以及服务和数据层。本文的代码示例(在 下载 中可以获得完整的代码包)演示如何使用这些接口帮助执行审计和减少数据访问对象(DAO)中的代码重复。

通用的基实体

与 对象不同,数据库表没有继承的概念。许多表中都有的字段(比如审计字段)必须为每个表重新定义。请牢记,可以在 Java™ 代码中使用继承,以避免这种重复出现在代码中。尽管 ORM 工具早就支持这个特性,但是 Java Persistence API 注解使之大大简化了,可以进一步减少代码重复(参见 参考资料)。

通过使用 Java 5 注解,可以用类级注解在类源代码中直接嵌入数据库映射。Java Persistence API 为此定义了一套标准注解。Hibernate 和其他工具现在支持这些注解。可以通过 @MappedSuperclass 注解使用在基类中定义的映射。只要所有数据库表对通用字段采用相同的列类型和列名,那么只需在基类中编写映射一次,就可以在所有子类中重用。清单 1 是 BaseEntity 类的一个示例:


清单 1. 用 @MappedSuperclass 定义 BaseEntity
                @MappedSuperclass
public class BaseEntity implements Identifiable{
private Long id;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}

清单 1 中的映射把 ID 字段映射到默认列名(id),并指定自动生成 ID(实现方式与数据库相关)。

注意,即使每个表使用不同的列名,仍然可能使用这些通用基字段。请考虑一种典型情况:所有数据库表的主键都是 Long 类型的,但是列名可能不一样。通过重新定义分配给特定子类的一个属性的列,仍然可以重用与 id 属性相关的代码。清单 2 演示如何重新定义与 id 属性相关联的列:


清单 2. 重新定义与 id 属性相关联的列



本文转自IBM Developerworks中国
   
请点击此处查看全文

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值