域模型
您可以把 JPA 看作是众所周知的透明持久性技术(如 JDO 和 Hibernate)的继承者。尽管透明持久性可看作一个附加(add-on)服务,可被应用到忽略持久性的
Plain Old Java Objects (POJO)中,但 JPA 还是对域对象施加了少量限制。
首先,您通常要具有一个映射到对应数据库表主键的(代理)对象标识符:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "AccountSeq")
@Column(name = "account_sysid")
public Integer getAccountId() {
return this.accountId;
}
|
其次,在联机事务过程(OLTP)环境中,需要一个 version 字段或 JavaBean 属性以进行乐观并发控制:
@Column(name = "row_version")
@Version
public int getVersion() {
return version;
}
|
最终,如果您选择使用注释方式的映射,映射注释将分布在代码周围。
另一种限制源自于这样一个事实:域对象可以通过由实体管理器所管理的域对象所在的层访问,也可以通过分离它的所有其他层访问。此外,对象可能是新的或已删除的。一般情况下,对象的行为取决于其持久性状态。例如,假设在实体管理器中执行以下这行代码:
int size = attachedProduct.getItems().size();
|
项集合使用给定产品的项填充,size 变量的值大于 0。如果使用默认懒加载(lazy)配置的一对多关联,并在表示层中执行同一行代码,size
变量的值为 0。 换句话说,在实体管理器之外(在实体管理器内也没关系)无法把 非活动(lazy)
对象与 活动(eager) 对象区分开。解决此问题的方法是强制执行项目规范和约定。
在域对象中,您可以把相同的推理应用到业务方法。无论是否在实体管理器中,它们都应该准备好在任何层中调用。这就是把域对象中的业务方法数量限制为必要的最少数量的理由。
虽然有上述各种情况,域对象依然保留许多 POJO 特性。这意味着您可以使用 plain old Java test
(POJT) 对业务方法进行测试,POJT 这一术语引自 Expert One-on-One J2EE Development
without EJB 一书。
OR 映射
OR 映射是围绕 JPA 设计的应用程序的重要元素。它直接影响实体管理器填充域对象的方式。因此,变更映射能够在表示层觉察到。变更获取类型或级联类型可能将产生非常不利的影响。
正如前面所述,有两种定义映射的方法:元数据(注释)和映射文件。尽管我们高度提倡采用元数据的方法,但您应该也注意到了它所带来的不便。从本质上讲,此方法牵涉应用程序的两个逻辑层:域模型和映射信息。因为这两个层是分散的,所以这两个层需要使用不同技术进行单独测试。元数据方法本身不会影响层的可测试性。更确切的说,元数据方法使这两个层好像只是一个层,由于受一系列因素的影响,这可能会引起问题。
影响映射方法选择的一个因素是项目小组结构。在只有少数开发人员参与的小型项目中,表的数量很少(一般说来少于 100
个表)而且没有专职的映射人员,因为通常使用注释会更加快速,所以把注释方法看作定义映射也许是最佳选择。对于拥有专职映射人员或映射小组的中型和大型项目来讲,使用映射文件的方法才是更好的选择。该方法可以降低资源争用并使开发过程具有另一种自由度。基于元数据的映射方法证实是
PetStore 应用程序更加节省时间的方法。
OR 映射层的目的是使其余应用程序免受底层数据库变更的影响。当把 PetStore 应用程序后端迁移到 PostgreSQL
时,无需对映射层作出任何变更。这可能要归结于这一事实:原始数据库和 PostgreSQL 这两者均支持序列,因此主键生成策略保持完好。一般情况下,您应该对与对象
ID 处理相关的映射区域进行重写。
对映射的全面测试覆盖极为重要。必须覆盖所有关系映射以确保对获取行为和过渡持久性进行测试。您能够利用容器外使用的
JPA 来执行该任务。