企业应用程序根据其需求而定义用于收集转换以与报告大.docx

上传人:b****4 文档编号:24234777 上传时间:2023-05-25 格式:DOCX 页数:18 大小:321.87KB
下载 相关 举报
企业应用程序根据其需求而定义用于收集转换以与报告大.docx_第1页
第1页 / 共18页
企业应用程序根据其需求而定义用于收集转换以与报告大.docx_第2页
第2页 / 共18页
企业应用程序根据其需求而定义用于收集转换以与报告大.docx_第3页
第3页 / 共18页
企业应用程序根据其需求而定义用于收集转换以与报告大.docx_第4页
第4页 / 共18页
企业应用程序根据其需求而定义用于收集转换以与报告大.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

企业应用程序根据其需求而定义用于收集转换以与报告大.docx

《企业应用程序根据其需求而定义用于收集转换以与报告大.docx》由会员分享,可在线阅读,更多相关《企业应用程序根据其需求而定义用于收集转换以与报告大.docx(18页珍藏版)》请在冰豆网上搜索。

企业应用程序根据其需求而定义用于收集转换以与报告大.docx

企业应用程序根据其需求而定义用于收集转换以与报告大

第1章

简介

 

企业应用程序根据其需求而定义,用于收集、转换以及报告大量的信息。

当然,这些信息必须保存在某处。

存储和检索数据是一个价值数十亿美元的业务,数据库市场的增长,以及非现场安全的数据存储和检索设施的出现,部分地证明了这一点。

尽管已有许多可用的数据管理技术,但是应用程序设计者依然花费了很多时间,试图将他们的数据有效地移入和移出存储器。

多年来,出现了许多持久化数据的方法,然而,没有任何方法比关系数据库具有更持久的生命力。

因此,目前世界上的企业数据,绝大多数存储在关系数据库中。

它们是每个企业应用程序的起点,并且通常在应用程序逐渐消失后,还将维持一段很长的寿命。

理解关系数据是企业开发成功的关键。

开发应用程序使之与数据库系统一起协调工作,是公认的软件开发的障碍。

Java成功的很大一部分应该归功于,其被广泛地用于构建企业数据库系统。

从消费者网站到自动网关,Java应用程序是企业应用程序开发的核心。

尽管Java平台成功地与数据库系统一起工作了很长时间,但是它也遭遇了一直困扰着其他面向对象编程语言的相同问题。

在数据库系统和Java应用程序的对象模型之间来回地移动数据,比实际所需困难得多。

Java开发人员或者需要编写大量的代码,将行和列数据转换成对象,或者发现自己被绑定到某些专用的架构中,这些架构试图对他们隐藏数据库。

幸运的是,平台中引入了一个标准的解决方案,即Java持久化API(JavaPersistenceAPI,JPA),以构建面向对象的域模型和关系数据库系统之间的桥梁。

本书将介绍JPA,探索它为开发人员所能提供的一切。

它的优势之一是,可以将它插入到应用程序所需的任何层(layer)、级(tier)或者架构(framework)中。

无论您是正在构建客户端/服务器(client-server)应用程序,用以在一个Swing应用程序中收集表单数据,还是在使用最新的应用架构建立一个网站,JPA都可以帮助您更有效地提供持久化。

为了有效地理解JPA,本章将首先回顾一下我们所处的位置,以及我们正在努力解决的问题。

其中,我们将了解规范形成的历史,并向您展现一个JPA必须提供的内容的高层次视角。

1.1对象-关系映射

“域模型(domainmodel)有类(class),而数据库有表(table)。

它们看起来非常相似,因此,在它们之间自动地互相转换应该很简单”。

当我们正在编写另一个数据访问对象(DataAccessObject,DAO),以转换Java数据库连接(JavaDatabaseConnectivity,JDBC)的结果集为面向对象的内容时,我们时不时都可能会有这样的想法。

域模型与数据库的关系模型看起来如此相似,因此,似乎应该寻找一种方法,使得两个模型可以互相交流。

用于在对象模型和关系模型之间搭建桥梁的技术,称为对象-关系映射(object-relationalmapping),通常表示为O-R映射或简写为ORM。

该术语来源于这样的思想:

我们正在以某种方式将一个模型的概念映射到另一个模型,目标是引入一个中介来管理一个模型到另一个模型的自动转换。

在介绍对象-关系映射的规范之前,先定义一下什么是理想的解决方案。

●对象,而不是表。

应用程序应该依据域模型进行开发,而无须绑定到关系模型。

必须能够在域模型上操作和查询,无须表示成关系语言的表(table)、列(column)以及外键(foreignkey)。

●方便,但非无知。

映射工具应该仅由熟悉关系技术的人使用。

O-R映射并不意味着开发人员不必理解映射问题或者完全隐藏它们。

这说明O-R映射适用于那些已经理解了映射问题,并且知道他们所需的开发人员,这些开发人员不想编写成千上万行代码来处理已经解决的问题。

●不显著,但非透明。

期望持久化是透明的是不合理的,因为应用程序总是需要控制它正在持久化的对象,并且关注实体(entity)的生命周期。

然而,持久化解决方案不应当干扰域模型,不必要求扩展域类或者实现接口是可持久化的。

●旧数据,新对象。

与创建一个新的数据库架构相比,应用程序更加可能连接到已经存在的关系数据库架构。

支持旧的架构是可能出现的最相关的用例之一,这种数据库的生命周期很可能比我们任何人更长久。

●充分,但不过分。

企业开发人员要解决许多问题,他们需要足够的功能以解决这些问题。

他们不喜欢被迫接受一个重量级的持久化模型,该模型将引入大的开销,因为它同时在解决很多人甚至不同意是问题的问题。

●本地,但可移动。

数据的持久化表示不必建模为一个完全成熟的远程对象。

分布式是应用程序的一部分,但不是持久化层的一部分。

然而,包含持久化状态的实体必须能够移动到任何需要它们的层。

这似乎是一个有点苛刻的需求集,但是它来源于实践经验和必要性。

企业应用程序都有非常具体的持久化需求,以上这个条目列表是企业社区经验的相当具体的表示。

阻抗失谐

对象-关系映射的倡议者通常把对象模型和关系模型之间的差异描述为两者之间的阻抗失谐(impedancemismatch)。

这是一个贴切的描述,因为将一个模型映射到另一个模型的挑战不在于两者之间的相似性,而在于每个模型中存在一些概念,这些概念在另外一个模型中没有任何逻辑等价物。

以下章节将介绍一些基本的面向对象的域模型,以及为持久化相同的数据集而设计的各种不同的关系模型。

您将看到,对象-关系映射的挑战,与其说是一个单一映射的复杂性,还不如说是因为有太多可能的映射。

我们的目标不是解释如何从一个点到达另一个点,而是理解为了到达某个预定目的地,可能必须采取的路径。

1.类的表示

图1-1Employee类

让我们以一个简单的类开始此次讨论。

图1-1显示了一个Employee类,该类具有4个特性:

员工ID、员工姓名、他们开始工作的日期,以及目前的薪酬。

现在考虑如图1-2所示的关系模型。

这个类在数据库中的理想表示对应于方案(A)。

类中的每个字段直接映射到表中的一列。

员工编号作为主键。

除了一些细微的命名差异,这是一个直接的映射。

图1-2三种用于存储员工数据的方案

在方案(B)中,可以看到该员工的开始工作日期实际上是存储为三个单独的列,分别存放天、月份和年份。

回想一下,这个类使用一个Date对象来表示此值。

因为数据库架构更加难以改变,是否应该强迫该类采用相同的存储策略,以保持对关系模型的一致呢?

同时请考虑该问题的相反方向,在该类中使用三个字段,而表中使用一个单一的日期列。

当数据库和对象模型采用不同的表示时,即使是单个字段,也将变成复杂的映射。

薪酬信息被视为商业敏感信息,所以把薪值直接放在EMP表中可能是不明智的,这可能会被用于许多目的。

在方案(C)中,已经拆分了EMP表,从而把薪酬信息存储在一个单独的EMP_SAL表中。

这使得数据库管理员可以限制对薪酬信息的SELECT(选择)访问权限,那些真正需要这些信息的用户拥有访问权限。

有了这样的映射,即使对于Employee类的单个存储操作,现在也需要插入或更新到两个不同的表。

显然,即使在数据库中存储单个类的数据也是一项具有挑战性的工作。

我们关心这些方案,是因为在生产系统中真实的数据库架构从未在设计时考虑对象模型。

在企业应用程序中的经验规则是,数据库的需要优先于应用程序的需要。

事实上,通常有许多应用程序,其中一些是面向对象的,而另一些是基于结构化查询语言(StructuredQueryLanguage,SQL),它们在一个单一的数据库中检索和存储数据。

多个应用程序依赖于同一数据库,意味着数据库的变化将会影响到每一个应用程序,显然,这是不可取的并且存在潜在的昂贵开销。

这取决于该对象模型能够适应并设法与数据库架构一起工作,同时不至于让物理设计优于逻辑应用模型。

2.关系

对象很少会孤立存在。

就像数据库中的关系一样,域类(domainclass)会依赖和关联到其他的域类。

考虑在图1-1中介绍的Employee类。

有许多域概念可以与一个员工相关联,但是现在将介绍Address域类,每个Employee类至多可能有一个地址实例。

我们说,在这种情况下Employee与Address存在一对一(one-to-one)的关系,在统一建模语言(UnifiedModelingLanguage,UML)模型中表示为0..1。

图1-3演示了这种关系。

图1-3Employee和Address的关系

上一节讨论了表示Employee状态的不同方案,同样有几种方法可以用来表示数据库架构中的关系。

图1-4演示了表示员工和地址之间一对一关系的三种不同的方案。

图1-4关联Employee和ADDRESS数据的三种方案

数据库中表示关系的基本单元是外键。

在每种方案中,各种表之间都涉及了外键关系,但是为了有一个外键关系,目标表必须有一个主键。

所以在关联Employee和Address之前,还有一个问题。

域类Address没有标识符,但是如果它要成为关系的一部分,那么存储它的表必须有一个标识。

可以利用Address表中所有的列构建一个主键,但是一般认为这是不好的做法。

因此,引入了一个ID列,并且对象-关系映射将不得不以某种方式来适应它。

图1-4中的方案(A)显示了这种关系的理想映射。

EMP表有一个指向ADDRESS表的外键,存储于ADDRESS_ID列。

如果域类关联到一个Address类的实例,那么地址的主键值可以在存储操作中设置。

然而考虑方案(B),它只是略有不同,但突然复杂得多。

在我们的域模型中,Address没有关联到拥有它的Employee实例中,然而该员工的主键必须存储在ADDRESS表中。

对象-关系映射必须考虑到域类与表之间的这种不匹配,或者必须为每个地址添加一个指向员工的反向引用。

为了使得事情变得更糟,方案(C)引入了一个关联EMP和ADDRESS表的连接表。

相对于直接在一个域表中存储外键,连接表关联一对键(key)。

与这两个表相关的每个数据库操作,现在都必须遍历该连接表并与它保持一致。

可以把一种EmployeeAddress关联类(associationclass)引入到域模型中以进行补偿,但是那将使得我们正在努力实现的逻辑表示失败。

关系为任何对象-关系映射解决方案都提出了挑战。

本章只涉及了一对一的关系,但是必须面对主键不在对象模型中,以及在模型中必须引入额外关系甚至关联类以补偿数据库架构的可能性。

3.继承

面向对象域模型的一种决定性要素,是有机会在相似类之间引入泛化的关系。

继承(inheritance)是用于表示这些关系的自然方式,并在应用程序中允许多态性(polymorphism)。

让我们重温图1-1中所示的Employee类,想象一个公司需要区分开全职和兼职员工。

兼职员工是按时薪结算,而全职员工则指定月薪。

这是继承的好时机,将工资信息移动到PartTimeEmployee和FullTimeEmployee子类。

图1-5显示了这一排列结构。

图1-5全职和兼职员工之间的继承关系

继承提出了对象-关系映射的一种真正问题,而不再是处理从一个类到一个表有一个自然映射的情况。

考虑如图1-6所示的关系模型。

这里再次演示了为保存相同数据集的三种不同的策略。

图1-6在关系模型中的继承策略

一些人认为,把继承结构映射到一个数据库,最容易的解决方案是,把每个类(包括父类)所需要的所有数据放置在单独的表中。

这一策略如图1-6中的方案(A)所示。

注意到表之间没有关系(即,每个表是独立于其他表的)。

这意味着,如果用户需要在一个单一的步骤中同时操作全职和兼职员工,那么对这些表的查询现在复杂得多。

一种有效的但非规范化的替代方法是将模型中每个类所需要的所有数据放置在单个表中。

这使得它很容易查询,但是请注意如图1-6方案(B)所示的表结构。

有一个新列TYPE,它在域模型中的任何部分都不存在。

TYPE列指出该员工是兼职或全职。

此信息现在必须由一个对象-关系映射解决方案来解释:

对于表中任何给定的行,知道实例化哪种类型的域类。

方法(C)更进一步,这次将全职和兼职员工的数据规范化到单独的表中。

然而,不同于方案(A),这些表由一个共同的EMP表所关联,该表存储了两个员工类型所有相同的数据。

单一的额外数据列看起来是多余的,但在一个真正的架构中,其中每种类型的员工有许多特定的列,很可能会使用此种类型的表结构。

它以一种逻辑形式表示了数据,并且也通过允许表连接在一起简化了查询。

但是,在数据库中运行效果很好的架构,并不一定适合映射到该架构的对象模型。

即使没有与其他类的关联,该域类的对象-关系映射现在必须考虑多个表之间的连接。

当开始考虑非持久化的抽象的超类或父类时,继承很快在对象-关系映射中变成了一个复杂的问题。

不仅面临着类的数据存储的挑战,而且复杂的表关系也难以有效地查询。

1.2Java持久化支持

从Java平台的初期开始,编程接口已经存在,用于提供连接到数据库的网关,并抽象出许多商业应用程序的特定于域的持久化需求。

接下来的几节将讨论当前和过去的Java持久化解决方案,以及它们在企业应用程序中的作用。

1.2.1专用解决方案

对象-关系映射解决方案已经存在了很长时间,甚至比Java语言本身更长,对此您也许会感到很惊讶。

诸如OracleTopLink之类的产品,在切换到Java之前,在Smalltalk世界中就已经存在。

在Java持久化解决方案历史上的一个莫大讽刺是:

实体bean初次实现的方式之一,实际上是通过在TopLink映射对象上添加一个额外的实体Bean层进行演示的。

两个最流行的专用的持久化API分别是:

在商用空间的TopLink和在开源社区的HibernateTM。

诸如TopLink的商业产品在Java的早期是可用的并且获得了成功,但是该技术从未针对Java平台而标准化。

后来,当诸如Hibernate的开源对象-关系映射解决方案变得流行时,Java平台中关于持久化的变化开始出现,最终导致对象-关系映射作为首选的解决方案。

这两个产品以及其他产品都可以轻松地集成到所有主要的应用程序服务器,并且为应用程序提供它们所需的所有持久化功能。

使用第三方产品,完全可以满足应用程序开发人员持久化的需要,特别是考虑到当前尚没有共同的和等效的标准的情况下。

1.2.2JDBC

1997年发布的Java平台的第二个版本,Java开发工具包(JavaDevelopmentKit,JDK)1.1,迎来了使用JDBC的数据库持久化的第一个重要支撑。

它是作为更通用的前身,即对象数据库连接(ObjectDataBaseConnectivity,ODBC)规范的一个特定于Java的版本而创建的,该规范是用于从任何语言或平台访问关系数据库的标准。

通过为数据库供应商提供的专用客户端编程接口,提供一个简单的和可移植的抽象,JDBC允许Java程序与数据库完全交互。

这种交互在很大程度上依赖于SQL,使得开发人员有机会运用数据库语言编写查询和数据操作语句,但是使用一个简单的Java编程模型来执行和处理。

JDBC的讽刺在于,尽管编程接口是可移植的,但是SQL语言是不可移植的。

尽管多次尝试将其标准化,但是编写任意复杂的SQL,使其将可以在两个主要的数据库平台上无变化的运行的情况依然很少。

即使在SQL方言类似的情况下,每个数据库还是会根据查询结构而执行不同的操作,在大多数情况下需要特定于供应商而进行调整。

此外,还有Java源代码和SQL文本之间紧密耦合的问题。

开发人员不断地受到“就绪”(ready-to-run)SQL查询的诱惑,在运行时动态地构建这些查询,或者简单地把它们存储在变量或字段中。

这是一个非常有吸引力的编程模型,直到有一天您意识到,应用程序不得不支持新的数据库供应商,并且它不支持您一直在使用的SQL方言。

即使SQL文本下降为属性文件或其他的应用程序元数据,但是总会存在当使用JDBC时,不但觉得不妥,而且它还会成为一种繁琐工作的情形,因为要把表格形式的行和列的数据不断来回地转换成对象。

该应用程序有一个对象模型—— 为什么使用数据库如此之难?

1.2.3企业JavaBean

第一个版本的Java2企业版(Java2EnterpriseEdition,J2EE)平台以实体Bean的形式为Java持久化引入了一个新的解决方案,它是企业JavaBean(EnterpriseJavaBean,EJB)组件系列的一部分。

为了充分避免开发人员直接处理持久化,它引入了一种基于接口的方法,其中具体的bean类从未被客户端代码直接使用。

取而代之的是,一个专门的bean编译器生成一个bean接口的实现,以方便持久化、安全性以及事务管理,从而将业务逻辑委托给实体bean实现。

实体bean的配置使用标准的和特定于供应商的XML部署描述符,它们由于复杂和冗长而声名狼藉。

公平地说,实体bean对于它们正试图解决的问题而言过度工程化(over-engineered)了,但具有讽刺意味的是,该技术的第一个版本缺乏许多执行实际业务应用程序所必要的功能。

实体之间的关系必须由应用程序进行管理,要求在bean类中存储和管理外键字段。

实体bean到数据库的实际映射,完全通过使用特定于供应商的配置来实现,正如Finder(用于查询的实体bean术语)所定义的一样。

最后,实体bean被建模为使用RMI和CORBA的远程对象,从而引入了网络开销,以及不应该一开始就添加到持久化对象的限制。

实际上,实体bean初始是用于解决分布式的持久化组件问题,该问题本不存在,但它导致了本地访问的轻量级持久化对象的常见问题。

EJB2.0规范解决了早期版本中发现的许多问题。

引入了容器托管(container-managed)实体bean的概念,其中bean类是抽象的,服务器负责生成子类以管理持久化数据。

引入了本地接口和容器托管的关系,从而允许定义实体bean之间的关联,并且由服务器自动保持一致。

此版本也引进了企业JavaBean查询语言(EnterpriseJavaBeansQueryLanguage,EJBQL),这种查询语言旨在与实体一起工作,可以可移植地编译成任何SQL方言。

尽管EJB2.0得到了改善,但是依然存在一个主要的问题:

过于复杂。

该规范假设开发工具将使开发人员避免配置和管理每个bean所需的许多工件(artifact)的挑战。

但是,这些工具要具体化的时间太长,因此即使EJB应用程序的规模和范围已经增加,负担依然完全落在了开发人员的肩上。

开发人员认为他们被复杂性所包围,没有任何有保证的基础设施可以使他们得以解脱。

1.2.4Java数据对象

部分由于EJB持久化模型的失败,以及没有令人满意的标准化的持久化API所导致的挫折,因此开始尝试另一个持久化规范。

Java数据对象(JavaDataObjects,JDO)主要由面向对象数据库(OODB)供应商所激励和支持,它并没有真正获得主流编程社区的支持。

它要求供应商增强域对象的字节码来产生二进制兼容的跨所有供应商的类文件,每一个兼容的供应商的产品必须能够产生和使用它们。

JDO也拥有一种查询语言,这种语言在本质上是绝对面向对象的,它没有得到占绝大多数的关系数据库用户的拥护。

JDO虽然是JDK的扩展,但是从未成为企业Java平台的集成部分。

它有许多有用的功能,被坚持它的一个小社群的忠实用户所接受,并且拼命试图推动它。

但是,主要的商业供应商对于应该如何实现持久化架构持反对意见。

由于规范得到的支持很少,因此JDO虽然经常被谈论,但很少使用。

有些人可能会认为,由于它的超前及其对字节码增强的依赖,才导致它受到不公平的待遇。

这可能是真的,如果在三年之后引入,那么它或许会被开发社区更好地接受,他们现在根本没把使用广泛运用字节码增强功能的架构当回事。

然而,一旦EJB3.0持久化运动开始实施,主要供应商都将签署成为新的企业持久化标准的一部分,这是JDO的不祥之兆。

人们很快向Sun抱怨,他们现在有两个持久化规范:

一个是企业平台的一部分,也可以在JavaSE环境下工作;另一个仅适合JavaSE规范。

此后不久,Sun公司宣布,JDO将缩减为规范的维护模式,JPA会充分利用JDO和持久化供应商,以成为以后单一支持的标准。

1.3为什么需要另一种标准

软件开发人员知道他们想要什么,但许多人在现有的标准中找不到答案,所以他们决定在别处寻找。

他们发现了一系列的专用的持久化架构,包括商业的和开源的。

实现这些技术的许多产品,采用了没有干扰域对象的持久化模型。

这些产品与实体bean不同,持久化对业务对象没有干扰,业务对象无需知道正在持久化它们的技术,它们不必实现任何类型的接口或者扩展一个特殊的类。

开发人员可以简单地对待持久化对象,就像任何其他的Java对象一样,然后将它映射到一个持久化存储,并使用持久化API来持久化它。

由于这些对象是普通的Java对象,因此将这种持久化模型称为简单旧式Java对象(PlainOldJavaObject,POJO)持久化。

由于Hibernate、TopLink以及其他持久化API已经在应用程序中存在,并完美地满足了应用程序的需要,因此一个问题经常被提及,“何必更新EJB标准以匹配这些产品已经能完成的工作?

为什么不继续使用这些已经工作多年的产品,或者为什么不基于开源的产品(如Hibernate)来执行标准化?

”确实存在许多理由说明为什么不能这么做,并且为什么这是一个坏的想法,即使它是可行的。

一个标准远比一个产品更深入,单一产品(甚至如Hibernate或TopLink一样成功的产品)不能体现一个规范,尽管它可以实现它。

作为核心,一个规范的意图是,它由不同的供应商实现,并且有不同的产品提供标准的接口和语义,这些接口和语义可以由应用程序假定,且不用把应用程序耦合到任何一款产品。

把标准绑定到一个开源项目,如Hibernate,会存在问题,甚至可能比Hibernate项目更糟。

想象一下,一个规范是基于一个开源项目的特定版本或代码库的检查点,那将会多么混乱。

现在想象一个开源软件(OpenSourceSoftware,OSS)项目,与由项目自身决定改变相反,它不能改变,或者只能在由一个特别委员会所控制的离散版本中,每两年改变一次。

如此,Hibernate以及任何开源项目,都很可能会窒息。

虽然标准化也许没有为咨询顾问或者五人软件店所重视,但对公司而言,它是很有价值的。

软件技术对于大多数IT企业而言是一项大的投资,当涉及巨额资金时,必须对风险加以衡量。

使用标准技术将大幅度地减少风险,并且如果证明最初的选择不能满足需要,那么它会允许公司能够更换供应商。

除了可移植性,标准化一项技术的价值同样体现在所有其他领域。

教育、设计模式和业界的沟通仅仅是标准化所带来的众多好处中的一些。

1.4Java持久化API

Java持久化API(JavaPersistenceAPI)是轻量级的、基于POJO的用于Java持久化的架构。

虽然对象-关系映射是该API的一个主要组件,但是,对于将持久化集成到可扩展的企业应用程序中所带给体系结构的挑战,它还提供了相应的解决方案。

下面的章节将浏览该规范的演变过程,并概述该技术的主要方面。

1.4.1规范的历史

Java持久化API是令人注目的,不仅因为它提供给开发人员的内容,而且也因为它出现的方式。

以下小节概述了对象-关系持久化解决方案的史前史和JPA的起源。

1. EJB3.0和JPA1.0

由于对利用Java构建企业应用程序的复杂性已抱怨了多年,因此“简化开发”是发布JavaEE5平台的主题。

EJB3.0带头并找到办法使企业JavaBean可以更便捷和更高效地使用。

在会话bean和消息驱动bean中,解决可用性的问题是通过简单地删除一些更繁重的实现需求,以及允许组件看上去更像普

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1