O/R Mapping基础
1、模型
(1)模型用来表示真实世界的实体
在科学和工程技术领域,模型是一个很有用途的概念,它可以用来模拟一个真实的系统。在软件开发领域,模型用来表示真实世界的实体。
(2)不同类型的模型
在软件开发的不同阶段,需要为目标系统创建不同类型的模型。
l 在分析阶段----需要创建概念模型
l 在设计阶段----需要创建域模型和数据模型
ü 其中,域模型是面向对象的,数据模型是面向关系的
ü 域模型和数据模型之间存在一种对象-关系映射。
(3)概念模型
l 概念模型清楚地显示了问题域中的实体
不管是技术人员还是非技术人员都能看得懂概念模型,他们可以很容易地提出模型中存在的问题,帮助分析人员及早对模型进行修改。
在软件设计域开发周期中,模型的变更需求提出得越晚,所耗费得开发成本就越大。
l 概念模型描述了每个实体的概念和属性,以及实体之间的关系:一对一、一对多和多对多
在现实生活中都可以找到相应的例子,例如一只母鸡有很多小鸡是一对多关系,一位客户选购了很多商品,而这些商品也可以被许多客户选购,这是多对多关系。
(4)关系数据模型
到目前为止,关系数据库仍然是使用最广泛的数据库,它存储的是关系数据。关系数据模型是在概念模型的基础上建立起来的,用于描述这些关系数据的静态结构,它由以下内容组成:
l 一个或多个表
l 表的所有索引
l 视图
l 触发器
l 表与表之间的参照完整性
(5)域模型
域模型由以下内容组成:具有状态和行为的域对象;域对象之间的关系。
2、域对象
(1)实体域对象
代表人、地点、事物或概念。通常,可以把业务领域中的名词,例如客户、订单、商品,当然也包括前面提到过的母鸡,作为实体域对象;
(2)过程域对象
代表应用中的业务逻辑或流程。它通常依赖于实体域对象。
(3)事件域对象
代表应用中的一些事件,例如异常、警告或超时等。
3、域对象之间的关系
在域模型中,类之间存在下面下面的的几种关系。
(1)关联(Association)
关联指的是类之间的引用关系(它使一个类指到另一个类的属性),这是实体域对象之间最普遍的一种关系。关联可以分为一对一、一对多和多对多关联。
(2)依赖(Dependency)
依赖指的是类之间的访问关系。如果类A访问类B的属性或方法,或者说是A负责实例化B,那么可以说类A依赖类B。
依赖对象通过调用被依赖对象的方法来获得服务。一种比较松散的关系,并且是短期的。我们的业务处理过程与对象往往依赖于我们的实体域对象。如在struts 的 action中调用模型层的方法。
(3)聚集(Aggregation)
聚集指的是整体与部分之间的关系,在实体域对象之间也很常见。其实聚合关系是关联关系的一种,是强的关联关系。聚合同时也体现整体和部分之间的关系。
例如,人与手就是聚集关系,在Person类中由一个hands集合,它存放被聚集的Hand对象:
public class Person
{
private Set hands = new HashSet();
…………
}
(4)组合
也叫合成关系,组成关系是关联关系的一种,是比聚合关系强的关系。对象负责代表部分的对象的生命周期。
(5)一般化(Generalization)
一般化指的是类之间的继承关系。
4、既然聚合,组合关系属于关联关系,那么如何区分一般关联关系,聚合关系和组合关系呢?
(1)一般关联
只要一个对象联系到另外一个对象就形成了关联关系。如:人和他的猫,黑豹乐队和窦魏,pc机和显示器。
(2)聚合关系
一种强关联关系,它要求有部分和整体的关系,并且没有了整体,部分也可以独立存在。
在上面例子中人和它的猫显然没有部分和整体的关系,所以只能是一般的关联关系。而黑豹乐队和窦魏,窦魏等人组成了黑豹乐队即:窦魏和黑豹是整体和部分的关系。而窦魏脱离了黑豹(早就离开了)更或者黑豹不存在了那么窦魏仍然可以以音乐人的身份存在(即对象仍然可以独立存在)所以它属于聚合关系。
组成关系是可以共享的。(窦魏也可以加入其他乐队)。
(3)组合关系
一种更强的整体和部分的关系。它并且要求代表整体的对象负责代表部分的对象的生命周期,组成关系是不能共享的。如:pc机和显示器的关系。
(4)注意的问题
如果两个实体是整体和部分的关系,那么它们到底是聚合还是组合,这取决于你的需求。比如说:pc机和显示器的关系,如果你的系统中,显示器脱离了pc机就不存在意义了,也可以说:所有显示器的访问都是通过pc机进行的,那么你可以把关系设定为组合(如你在为一个只买品牌机的代理商作系统你可能是可以这么作的)。
如果你的显示器脱离的pc机仍然可以独立存在,也就是说在系统中可以直接访问显示器对象,那么你可以将关系设为聚合(如你在为一个买散件的代理商作系统你可能是可以这么作的)
5、域对象的持久化概念
(1)什么是持久化
狭义的理解,“持久化”仅仅指把域对象永久保存到数据库中;广义的理解,“持久化”包括和数据库相关的各种操作。
(2)为什么要进行持久化
当实体域对象在内存中创建后,它们不可能永远存在。最后,他们要么从内存中清除,要么被持久化到数据存储库中。内存无法永久地保存数据,因此必须对实体域对象进行持久化。否则,如果对象没有被持久化,用户在应用运行时创建地订单信息将在应用结束运行后随之消失。
(3)什么域对象需要持久化
当然,并不是所有的域对象都需要持久化,通常只有实体域对象才需要持久化,另外,有些实体域对象也不需要持久化。
(4)持久化类
持久化类是指其实例需要被Hibernate持久化到数据库中的类。持久化类通常都是域模型中的实体域类,同时持久化类符合JavaBean的规范,包含一些属性,以及与之对应的getXXX()和setXXX()方法。
6、数据访问有哪些模式
从数据库技术诞生到现在,已经有了数十年的历史;相应的,从最早的读写磁盘文件开始,数据访问技术也不断的推陈出新,变得越来越丰富。在最初的日子里,不同的数据库厂商会提供不同的访问接口,开发人员需要针对每种数据库学习不同的访问技术,比如 DB2 系统的 CLI Library 或是 Oracle 的 OCI Library。再到后来,数据访问中间件的思想得到了发展,出现了最初的 ODBC(Open Database Connectivity:开放数据库连接)以及其它一些类似的访问技术。
在 C 和 C++ 流行的年代里,这项技术在微软的推动下不断发展,后来又有了诸如 OLE DB(Object Link and Embedding Database)以及 ADO(ActiveX Data Object)等数据访问技术,它们直到今天还运行在世界各地成千上万的系统中。
(1)业务逻辑层包含了业务数据和业务过程
l 实体域对象
在分层的软件结构中,业务逻辑层代表了业务数据和业务逻辑。域对象位于业务逻辑层,实体域对象代表应用运行时的业务数据,它存在于内存中,并借助于数据库实现用于存放永久性的业务数据。
业务数据在内存中表现为实体域对象形式,而在关系数据库中表现为关系数据形式。数据访问代码负责把实体域对象持久化到关系数据库中。
l 过程域对象
过程域对象代表应用的业务逻辑。
(2)数据访问模式----持久层的混杂模式
(3)数据访问模式----基于业务实体类的持久层实现模式(业务逻辑和数据访问耦合)
在此种模式种的过程域对象中,业务逻辑和数据访问代码混杂在一起,参见下图。
(4)数据访问模式----主动域对象模式
由实体域对象负责自身的数据访问细节,这种实体域对象也被称为主动域对象,参见下图种的说明。J2EE平台中的BMP EJB组件就是采用主动域对象模式的一种应用示例。
(5)数据访问模式----DAO 模式
DAO 模式是标准 J2EE 设计模式之一,开发人员常常用这种模式将底层数据访问操作与高层业务逻辑分离开。一个典型的 DAO 实现通常有以下组件:
l 一个 DAO 工厂类
l 一个 DAO 接口
l 一个实现了 DAO 接口的具体类
l 数据传输对象(有时称为值对象)
(6)数据访问模式----ORM模式
在此种模式中,采用在单独的持久化层由ORM中间件封装数据访问细节,参见下图。而ORM中间件提供对象---关系映射服务,当向数据库保存一个域对象时,把业务数据由对象形式映射为关系数据形式;当从数据库加载一个域对象时,把业务数据由关系数据形式映射为对象形式。
(7)数据访问模式---- JDO模式
Java Data Objects(JDO)是SUN公司制定的描述对象持久化语义的标准API。因此采用JDO模式时,整个应用为四层应用结构,参见下图所示。
严格的说,JDO并不是对象-关系映射接口,因为它支持把对象持久化到任意一种存储系统中,包括: 关系数据库和面向对象的数据库。
(8)数据访问模式----CMP模式
在J2EE架构中,CMP(Container-managed Persistence)表示由EJB容器来管理实体EJB的持久化,EJB容器封装了对象-关系的映射以及数据访问细节。
CMP与ORM的相似之处在于,两者都提供对象-关系映射服务,都把对象持久化的任务从业务逻辑程序中分离出来;区别在于CMP负责持久化实体EJB组件,而ORM负责持久化POJO,它是普通的基于Java Bean形式的实体域对象。
CMP和ORM相比,前者有以下不足:
l 开发人员开发的实体EJB必须遵守复杂的J2EE规范,而多数ORM中间件不强迫域对象必须满足特定的规范。
l 实体EJB只能运行在EJB容器中,而POJO可以运行在任何一种Java环境中。
l 目前,对于复杂的域模型,EJB容器提供的对象-关系映射能力很有限。相比之下,许多ORM中间件提供了完善的对象-关系映射服务。
l 尽管按照J2EE的规范,EJB应该是一种可移植的组件,实际上却受到很大限制。因为不同厂商生产的CMP引擎差异很大,它们使用的对象-关系映射元数据各不相同,使得EJB不能顺利的从一个EJB容器移植到另一个EJB容器中。
使用ORM中间件就不存在这样的问题,以Hibernate为例,它可以无缝集成到任何一个Java系统中。在Java软件架构领域,在出现基于CMP的实体EJB之前,基于JavaBean形式的实体域对象早就存在了。但是把基于JavaBean形式的实体域对象称为POJO,却是最近才发生的事。
POJO(Plain Old Java Object----又普通又古老的Java对象),它和基于CMP的实体EJB相比,既简单,又具有很高的可移植性,因此联合使用ORM映射工具和POJO,已经成为一种越来越受欢迎的,用于取代CMP的持久化方案。
7、Java平台中的各种数据持久化技术
大多数应用程序都需要处理数据。Java应用程序运行时,往往把数据封装为相互连接的对象网络,但是当程序结束时,这些对象就会消失在一团逻辑中,所以需要有一些保存它们的方法。
有时候,甚至在编写应用程序之前,数据就已经存在了,所以需要有读入它们和将其表示为对象的方法。手动编写代码来执行这些任务不仅单调乏味、易于出错,而且会占用整个应用程序的很大一部分开发工作量。
(1)JDBC
大多数Java开发员都是用JDBC来和数据库进行通信,它可以通过DAO(Data Access Object)模式来进行改善和提高,然而,这种方式在大型应用程序中则会造成维护的"高消费"。JDBC 提供了还算不错的数据库抽象,但是需要用痛苦的API。这些问题包括:
l 需要冗长的错误处理代码来确保ResultSets,Statements以及(最重要的)Connections在使用后关闭。这意味着对JDBC的正确使用可以快速地导致大量的代码量。它还是一个常见的错误来源。Connection leak可以在有负载的情况下快速宕掉应用程序。
l SQLException相对来说不能说明任何问题。JDBC不提供异常的层次,而是用抛出SQLException来响应所有的错误。找出到底哪里出错了——例如,问题是死锁还是无效的SQL?——要去检查SQLState或错误代码。这意味着这些值在数据库之间是变化的。
(2)EJB
据调查EJB通常是在数据持久技术上的第二个选择,它是通过EntityBeans来对数据进行持久化。但我们首先必须购买一个价位合理的EJB容器--J2EE应用服务器;
其次全面采用EntityBean需要花“大量”的时间来理解EJB规范。在采用EJB之前你通常想在熟练掌握它的API;
再有就是,你需要知道在每一个容器除了ejb-jar.xml以外所专有的部署描述符。对于JAVA开发员,在EJB中实现JDBC也比较复杂。
EJB中最为被关注的可能是无状态的会话BEAN(stateless-Session beans)和消息驱动BEAN(messaging driver beans)
(3)Hibernate技术
如何实现使这些工作自动化?如果每一种数据库管理系统都有它自己的方言,我们如何达到可移植性?答案是使用Hibernate技术
Hibernate技术的目标是成为Java中管理持续性数据问题的一种完整的解决方案。它协调应用与关系数据库的交互,让开发者解放出来专注于手中的业务问题。
Hibernate是一种非强迫性的解决方案。我们的意思是指在写业务逻辑与持续性类时,不会被要求遵循许多Hibernate特定的规则和设计模式。这样,Hibernate就可以与大多数新的和现有的应用平稳地集成,而不需要对应用的其余部分作破坏性的改动。
8、在关系数据库上建立对象模型(ORM技术)
(1)在关系数据库上建立对象模型
对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射(ORM)系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。
为了弥补关系数据库在数据结构表示中的不足,我们可以扩展传统的关系型数据库,在关系数据库上加一层面向对象的逻辑层,该逻辑层为上层应用开发提供面向对象概念的表示方法,同时与底层数据库之间建立对象-数据映射关系。这一逻辑层也可称为对象模型层。
(2)其实现的核心思想
这一方案从下至上解决关系数据库的局限性,其核心思想是:对上层软件提供一个统一的面向对象的数据模型,即提供各类面向对象的概念和数据结构以及对此的各类维护操作和柔性扩展;对于底层则屏蔽具体数据库的关系模型,并利用映射原理建立透明的对象转换机制,并对底层数据库进行合理有效的管理。
(3)对象模型层的映射原理
是上层面向对象的数据模型与底层数据库的关系模型之间的对应转换关系。利用这层转换关系,可以使上层应用开发不必关心对象模型在底层数据库的存放以及底层数据库的各类维护工作。
(4)对象和关系数据库中的基本概念映射对照如下表所示
关系模型 | 对象模型 |
表 | 类 |
记录 | 对象 |
主键 | 对象标识 |
列/字段 | 属性 |
表层次 | 类层次 |
子表 | 子类 |
父表 | 超类 |
9、ORM技术
(1)什么是ORM?
简单地说,对象-关系映射就是Java应用中的对象到关系数据库中的表的自动的(和透明的)持续化,使用元数据对对象与数据库间的映射进行了描述。本质上,ORM的工作是将数据从一种表示(双向)转换为另一种。
(2)ORM解决方案有以下四部分组成
l 在持续类的对象上执行基本的CRUD操作的一组API。
l 用于指定查询的一种语言或一组API,这些查询会引用类和类属性。
l 用于指定映射元数据的工具。
l 实现ORM的一项技术,用来与事务对象交互以完成脏检查、懒关联存取和其它优化功能。
(3)为什么要应用ORM解决方案
l 可以节省大量的开发工作量,简少烦琐的SQL语句编写
运用O/R Mapping模式去开发数据库应用可以节省大量的工作量,特别是烦琐的SQL语句编写。虽然O/R Mapping有它的好处,但也有人说它不好有很大性能问题;他们认为反复地将对象和SQL之间的转换和大量的反射操作会带来很大性能问题。
l 能够以对象为单位进行相应的数据库操作
在JDBC中我们是怎么保存对象内容到数据库中的?当然是把对象的一个个属性单独拿出来,挨个操作。整个操作是以类的属性为单位,不再是以对象为单位操作了。
那我们如何可以做到以对象为单位保存数据呢?ORM则提供了这样一种机制:对象到关系的映射。
l 其它方面的考虑:事务、缓存等技术的应用
O/R Mapping工具----Hibernate技术基础
1、Hibernate基本概念
(1)Hibernate技术本质上是一个提供数据库服务的中间件
l Hibernate 是一个面向Java 环境的对象/ 关系数据库映射工具,把Java类对应到数据库的table中,并且采用了xml技术、Java Reflection技术等。
l Hibernate技术本质上也是遵守的ODMG标准的,它的出色源于不断的升级、不断的维护、修改。以及完善的文档、人气很旺的论坛。还有很重要的一点就是它的易学易用性。
l Hibernate它不仅提供了从Java类到数据表的映射,也提供了数据查询和恢复等机制。可以大幅度减少开发时人工使用SQL 和JDBC 处理数据的时间。
(2)Hibernate是一个开放源代码的对象关系映射框架
l 以OO的方式来操纵数据库
它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
l Hibernate可以应用在任何使用JDBC的场合
Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序实用,也可以在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。
try
{
stmt=con.createStatement();
rs=stmt.executeQuery("select * from student");
metaData = rs.getMetaData();
for(int column = 0; column < metaData.getColumnCount(); column++)
{
System.out.print(metaData.getColumnName(column+1)+"/t");
我们都写过这样的JDBC代码 |
System.out.println("");
while(rs.next())
{
for (int i = 1; i <= metaData.getColumnCount(); i++)
{
System.out.print(rs.getObject(i)+"/t");
}
System.out.println("");
}
stmt.close(); //must close
con.close();
}
catch(SQLException e)
{
}
(3)主要的特点及与Entity EJB Bean的不同点
l Hibernate是JDBC的轻量级的对象封装
它是一个独立的对象持久层框架,和应用服务器以及和EJB没有什么必然的联系。Hibernate可以
用在任何JDBC可以使用的场合,从某种意义上来说,Hibernate在任何场合下取代JDBC;
Hibernate是一个和JDBC密切关联的框架,所以Hibernate的兼容性和JDBC驱动,和数据库都有一定的关系,但是和使用它的Java程序和应用服务器没有任何关系,也不存在兼容性问题。
Hibernate是做为JDBC的替代者出现的,不能用来直接和Entity Bean做对比。但我们所应该注意的是:无论是基于CMP的实体EJB,还是基于BMP的实体EJB,它们的共同特点是都必须运行在EJB容器中。而Hibernate支持的持久化类不过是普通的Java类,它们能够运行在任何一种Java环境中。
l 当然EJB具有分布式的特性,而Hibernate则不具备
EJB的分布式的特性主要是体现在数据访问的分布式和事务管理的分布式等方面。不过在EJB1.x和2.x中,实体bean使用起来非常困难,这有两个原因:
ü EJB 1.x和2.x实体bean必须符合严格的组件模型。每个bean类必须实现本地接口和业务接口。它们必须从某些抽象类继承而来,还要实现所有方法,即便许多方法是空的。
ü EJB 1.x和2.x容器需要极其冗长的XML配置文件把实体bean映射到关系数据库里面的表。那些文件非常冗长,还容易出错。
(4)应用层和持久层的关系
l 持久(Persistence)。简单来讲,也就是把数据保存到可掉电式存储设备中供之后使用。
l 所谓“持久层”,也就是在系统逻辑层面上,专注于实现数据持久化的一个相对独立的领域(Domain)。
l 我们一般将应用层放在持久层的上部,实际上在传统的项目中,应用层充当着持久层的一个客户端角色。但对于一些简单的项目来说,应用层和持久层并没有区分得那么清楚,在这种情况下可以将应用层和持久层合并成为一层。
(5)持久层设计与解耦合
l 何谓耦合:通俗地讲,就是事物之间的相互关联关系。
l 何谓解耦合:即采用一些手段降低关联的紧密程度。
l 解耦合设计的目标
ü 应用层解耦合――应用逻辑与数据逻辑相分离
ü 资源层解耦合――逻辑结构与物理结构相分离
借助于Hibernate,我们基本上能够实现跨数据库的应用系统。但我们在开发中也应该尽可能考虑到不同数据库之间的差别的特性。诸如MS SqlServer的text/image字段上不能查distinct,Oracle内的各种对象名称长度不得超过30个字符等;另外,也尽量不要应用数据库的内部特性(如存储过程、视图等)。
(6)利用Hibernate技术不仅提高了编码的效率,同时也提高了数据库访问性能优化
l 提高了编码的效率
Hibernate是一个ORM工具,它不仅仅是实现了数据库访问性能优化和与数据库交互的常用操作(CRUD),还将数据表与对象进行了关联,让我们可以脱离数据表,而直接针对对象来与数据库交互,我们不再需要用字符串去描述表中字段,不再需要一个个”+“号去 组装Sql语句。这使得编码中可书写性提高。
l 提高了数据库访问性能优化
同时也不需要我们考虑与数据库交互的性能问题,如连接池、数据缓存等等。因为Hibernate提供了强大的功能以实现:数据读取和更新、事务管理、数据连接池、查询和实体关系管理等。
2、为什么要使用Hibernate工具
Hibernate是业界一个比较成熟并且流行的O/R Mapping框架。
l 说它成熟是因为它提供了一个O/R Mapping产品最主要的功能------比如数据库映射、连接池管理、事务支持等等。更重要的是,它提供了对多种数据库产品的支持。因此,其O/R Mapping和多数据库支持更能够吸引开发者。
l 说它流行是因为太多的人使用了,不论是从实用开发的角度出发,还是从研究的角度出发,甚至是从赶时髦的角度出发。从对于没有自己的数据持久层开发能力的开发者角度来看,hibernate的确能够为他们带来开发效率的提高和改进软件架构。
(1)为应用系统提供统一的一致的数据库访问操作
l JDBC技术
在常规的Java应用系统中的数据库访问技术使用的是JDBC并且进行JDBC编程。当项目越来越大时,觉得JDBC到处建立连接,或者使用直接的sql语句,修改或者项目变更起来很不方便;于是产生了数据访问的程序的应用需求,所有的数据访问都通过这个程序转换为JDBC的代码来访问数据库。
l 使用Hibernate API访问数据库
下图的左面是通过JDBC API访问数据库,而右图则是通过Hibernate API访问数据库。
l 使用Hibernate API访问数据库的基本的过程
首先应该在应用的启动阶段对Hibernate进行初始化,然后就可以通过Hibernate的Session接口来访问数据库。
l 优点
这种技术的采用确实给开发工作带来了十分的改观,所有的对数据库的操作变成了对某个对象的操作,并且采用Java语言特有的Reflection机制,动态的取得某个JavaBean的属性,然后对应到(mapping)某个数据库的表中,这样,客户端的代码就变得非常简单。
(2)Hibernate 的最大特点就是数据持久化
l 提高开发效率
Hibernate 不仅仅管理Java 类到数据库表的映射,还提供数据查询和获取数据的方法,可以大幅度减少开发时人工使用SQL 和JDBC 处理数据的时间;同时Hibernate封装了数据库访问、事务管理、数据缓存等工作。省去了自己去编写这些代码。
l 可以看出Hibernate 的最大特点就是数据持久化。
(3)不用写SQL语句,甚至不需要懂得SQL语言!
在应用Hibernate时,只要我们定义好了持久类与数据库中表字段的对应关系,Hibernate会自动帮你生成SQL语句来对持久类对象进行插入、更新、删除、查找工作,你可以不写一句SQL语句,甚至不需要懂得SQL语言!
l 传统的数据库访问代码
insert into table (field_1,field_2,field_n) values('"+ field_value1 +"','" + field_value2 + "','" + field_value3 + "'")
l 借助Hibernate后数据库访问代码
session.save(table_Object)
由代码比较可以看出,数据表可以跟对象一样被操作,这样代码显得更加简洁,可读性也增强。在实际开发中,这里是业务变动 频繁的地方,保证代码的可读性和易维护,很有价值。
(4)支持各种主流的数据源
目前所支持数据源包括:HypersonicSQL、PostgreSQL、DB2、MySQL、Oracle、Sybase、Mckoi SQL、SAP DB、MS SQL Server、JSQL Driver、JTURBO Driver、WebLogic Driver、纯Java驱动程序等。
(5)Hibernate的一些弱点
Hibernate作为流行的企业应用和关系数据库之间的持久化中间件,受到越来越多的关注。虽然使用Hibernate可以使得项目易于维护,帮助开发人员更好地处理复杂关系模型,提供了很强的方便性,但却失去了JDBC原有的灵活性。如何在“灵活”与“方便”之间取舍、平衡显得重要起来。
l 主要体现在比如对象关系的映射配置过多,控制复杂;事务处理面临各种兼容问题;HQL语言增加学习成本等。也就是“灵活”的背后隐藏着“复杂”,“方便”的背后隐藏着“不便”,如何取舍与平衡,还是看实际需要。
l Hibernate内置映射类型复杂化
在开发过程中,时常会查找Hibernate映射类型--Java类型--标准SQL类型之间的关系。繁杂之处体现在两方面,一是各种数据库的数据类型和标准SQL之间会有一定的出入,二是Hibernate映射类型虽然大部分和Java类型相同,但也存在比较晦涩的地方,例如character类型对应Java的char / java.lang.Character / java.lang.String,text对应着Java的java.lang.String。
l ID规定化生成
Hibernate中内置标识符生成器给表单ID自动生成提供了方便,但却不能自定义各种ID形式。
l 是不支持动态映射数据库表
由于在Hibernate中的persistent object是通过XML Mapping文件映射到数据库表上,这样就不能动态映射不同的表,比如有时候会遇到根据不同的情况选择是从当前表还是从历史表中进行查询就比较困难。
比如我们的系统中的数据库表很多都是临时生成的(但是表结构都一样,就是表名字不一样)。但是hibernate中要指明具体的表的名字。
3、Hibernate和JDBC在性能上的对比
(1)主要用hibernate开发的系统能提高开发效率和系统的可重用性等。
因为任何封装在JDBC之上的东西都不可能有直接去写JDBC快(不考虑cache)。但通过适当的封装,这样能够降低开发的复杂性,提高开发效率和使代码易于维护。
(2)能够真正实现面向对象的建模
用Hibernate时最大的便利不是在写代码的时候用对象的操作代替SQL语句,而是在建模的时候可以用面向对象的思维把很复杂的逻辑用UML图表示出来,然后直接转化成实体。
(3)JDBC+Hibernate相互结合
所以我们在性能影响太大的地方采用了面向对象和关系相结合的方式,但在更多的地方仍然只能采用对象关联的方式。
4、什么时候使用Hibernate
那么在什么情况下选择使用hibernate来构建自己的数据持久层呢?
(1)自己没有数据持久层开发能力
由于hibernate为我们提供了一套成熟的O/R Mapping的模型,应用它将能够在短时间内构建适合业务需求的数据持久层的解决方案--------当然,前提是要对hibernate有基本的使用开发能力。
(2)对JDBC底层开发不甚熟悉者.
由于hibernate实现了对JDBC底层的调用封装,这样将能够统一对不同类型的数据库系统的支持。因此,当开发者在缺乏对JDBC底层调用的了解时,使用Hibernate则可以达到事半功倍的效果。
(3)在团队开发中希望能够统一持久层开发
从技术上来分类,我们一般是把hibernate称为O/R Mapping开发框架。因此,既然是框架,那么如果团队中的各个成员对这个框架比较熟悉的话,那么我们将可以统一团队的开发过程,从而减少沟通的频率,同时也能够促进协同开发和数据共享。
(4)自己开发的数据持久层不能满足业务需求
如果缺乏对JDBC的了解和数据持久层开发的经验,可能自己开发的数据持久层会慢慢的不满足业务需求。比如在数据缓存、连接池管理、多数据库支持等等方面,hibernate在上述方面有比较出色的表现。因此,我们可以在不影响业务功能实现的开发前提下可以考虑采用该框架。
(5)希望我们的应用系统不依赖于某种特定的数据库
如果我们的应用系统使用了某种数据库系统,比如MS-SQL2000数据库,但可能某一天我们的客户会要求我们将产品迁移到Oracle。为什么要迁移到Oracle系统,其理由很简单--------客户原来就有购买的Oracle数据库,不希望再增加数据库方面的投资了。但是,我们只能很遗憾的告诉客户,我们的产品只能使用MS-SQL2000数据库。这样无疑,我们将可能失去一个重要的准客户。
因此,在企业级的开发中,我们希望应用系统能够满足不同的物理数据库系统的差别所带来的问题。这样在设计方面,将系统设计为一款通用产品------那我们就需要在设计和实现两个方面做许多工作。
那么,我们如何设计适用于多种类型数据库的通用产品而不是提供多个产品版本呢?
由于JDBC本身就是数据库独立的,即不依赖于具体的数据库类型。因此,我们可以从以下几个方面进行把握。
l 尽量使用标准通用的SQL语句
l 尽量不使用各数据库方言和某种数据库特有的函数或者数据类型
l 将配置参数保存在一个properties文件或者*.xml中,然后在代码中利用类似Configuration.setProperties(Properties pro)方法载入配置参数文件。
5、Hibernate系统
其实Hibernate本身是个独立的框架,它不需要任何web server或application server的支持。
(1)Hibernate的设计者Gavin King
Gavin King是Hibernate的作者,EJB3.0专家委员会成员,JBoss核心成员之一。Hibernate诞生在2001年11月。Gavin King 1974年出生于澳大利亚,现在居住在澳大利亚默尔本市。
(2)下载
hibernate是sourceforge的一个子项目,我们可以从Hibernate 的网站http://www.hibernate.org/(Hibernate 的中文网站是http://www.hibernate.org.cn/)或者http://hibernate.sourceforge.net上面获得下载的连接。
(3)架构
l 上图显示了hibernate的工作原理
它是利用数据库以及其他一些配置文件如hibernate.properties,XML Mapping等来为应用程序提供数据持久服务的。
l Hibernate是Java应用和关系数据库之间的桥梁
它负责Java对象和关系数据之间的映射。Hibernate内部封装了通过JDBC访问数据库的操作,向上层应用提供了面向对象的数据访问API。
(4)“轻型”的体系结构方案
我们应用系统中的持久类是一种普通的JavaBean(JOPO),因此不依赖于Hibernate的API。
(5)“全面解决”的体系结构方案
它是将应用层从底层的JDBC/JTA API中抽象出来,而让Hibernate来处理这些细节----从而可以屏蔽各个物理数据库系统的差别。
(6)几个主要的工具功能
l hbm2java是根据映射文件自动生成java源文件
l hbm2ddl 是根据映射文件自动生成数据库schema
l XDoclet 根据带有XDoclet的标记的java源文件生成映射文件
l Middlegen 根据数据库Schema自动生成映射文件
6、Hibernate API中包含的一些主要的类
(1)Hibernate的接口大致可以分为以下几种类型:
l 一些被用户的应用程序调用的,用来完成基本的创建、读取、更新、删除操作以及查询操作的接口。这些接口是Hibernate实现用户程序的商业逻辑的主要接口,它们包括Session、Transaction和Query等。
l Hibernate用来读取诸如映射表这类配置文件的接口,典型的代表有Configuration类。
l 回调(Callback)接口。它允许应用程序能对一些事件的发生作出相应的操作,例如Interceptor、Lifecycle和Validatable都是这一类接口。
l 一些可以用来扩展Hibernate的映射机制的接口,例如UserType、CompositeUserType和IdentifierGenerator。这些接口可由用户程序来实现(如果有必要)。
Hibernate使用了J2EE架构中的如下技术:JDBC、JTA、JNDI。其中JDBC是一个支持关系数据库操作的一个基础层;它与JNDI和JTA一起结合,使得Hibernate可以方便地集成到J2EE应用服务器中去。
(2)Hibernate一共包括了几十个jar包,令人眼花缭乱
下文将讲解Hibernate主要的jar包的作用,便于你在应用中根据自己的需要进行取舍。
l SessionFactory (org.hibernate.SessionFactory):包含已经编译的映射(mappings),是制造session的工厂,可能含有一些可以在各个事务(transaction)之间共享的数据。
l Session (org.hibernate.Session) :单线程的,短寿命的对象,代表了一次会话的过程。实际上是把一个JDBC Connection打包了,它可以包含一些持久化对象的缓存。
l Persistent Objects and Collections:单线程的,短寿命的对象,包含了各种属性字段以及一些商业逻辑,它们可能仅仅是一些普通的javabeans,但是它必然在某个时刻只能和一个session相关联。
7、有关Hibernate的中文资源
(1)中文论坛(http://www.hibernate.org.cn)
Hibernate中文论坛是中国最早的Hibernate专业用户论坛,为Hibernate在中国的推广做出了巨大的贡献,目标是成为一个高品质的,有思想深度的、原创精神的Java技术交流网站,为软件从业人员提供一个自由的交流技术,交流思想和交流信息的平台。
(2)中文参考书
《深入浅出Hibernate》是国内第一本围绕Hibernate3进行讲解的技术书籍。
8、Hibernate的应用场合---Hibernate可以配置成可在任何Java环境中运行
Hibernate可以配置成可在任何Java环境中运行,一般说来,它通常被用在2-3层的C/S或者B/S模式的项目中,并被部署在服务端。
在这种项目中,Web浏览器、或Java GUI程序充当者客户端。尽管我们的焦点主要是集中在多层Web应用,但实际上在一些基于命令行的应用中也可以使用Hibernate。
9、Hibernate系统可以运行在两种环境下
Hibernate可以与任何一种Java应用的运行环境集成,Java应用的运行环境可分为两种:受管理环境(Managed environment)和不受管理环境(Non-managed enviroment)。
(1)受管理环境――应用系统的整个执行过程在容器的控制之下
此时容器可为应用系统管理如下资源:池资源管理,诸如数据库连接池、还有事务管理、安全定义。一些典型的J2EE服务器(JBoss、Weblogic、WebSphere)已经实现了这些。
(2)不受管理环境――应用系统的整个执行过程不在容器的控制之下
l 由应用本身负责管理数据库连接、定义事务边界以及管理安全。
l 独立的桌面应用或命令行应用都运行在不受管理环境中。
l Servlet容器会负责管理线程池,有些Servlet容器,如Tomcat,还会管理数据库连接池,但是Servlet容器不会管理事务,因此它提供的仍然是不受管理的运行环境。
(3)Hibernate允许Java应用在不同的环境中移植
当Java应用从一个环境移植到另一个环境中时,只需要修改Hibernate的配置文件,而不需要修改或者只需要修改极少量的Java源代码。
10、如何学习Hibernate
(1)Hibernate文档
Hibernate文档处处都是持久层设计的经验和最佳实践。Hibernate文档准确的来说,绝大部分内容都在讲对象的持久层设计,而不是简单的Hibernate使用。
(2)学习要点
l 所以学习Hibernate,主要是在学习持久层的设计模式,如果你把Hibernate文档都看完了,还整天只会提那些 Hibernate的配置问题,Hibernate的类调用问题,我觉得这样的人还没有真正的入门,算是白学了
l 在学习Hibernate的时候即集中所有精力来理解Hibernate的运行原理,集中精力来掌握持久层设计应该把握的原则和技巧,这些才对我是最重用的东西----而如果在学习Hibernate时间,主要侧重于怎么配置,用工具怎么生成hbm文件,如果你把重点放在这里,基本上等于白学了Hibernate。
因为,如果这样进行学习,学习完Hibernate,肯定会对JDBC的编程也提高了一大截,更不要说对于J2EE架构的持久层的框架设计,基本上是了然于胸了,即使将来换了API,不用Hibernate的,改用JDO,Castor什么的,这些经验一样照用。
(3)Hibernate的精华:在于无与伦比的灵巧的对象持久层设计
这些持久层设计经验不会因为你不用Hibernate而丧失掉,我自己学习Hibernate,已经明显感觉到对持久层设计能力已经长了很多经验值了,这些经验甚至不光可以用在Java上,用在.net上也是一样。
因为,不管JDO也好,Hibernate也好,TopLink也好,CocoBase也好,还是Castor,还是什么Torque,OJB,软件的使用和配置方法可以各异,但本质上都是ORM,都是对JDBC的对象持久层封装,所以万变不离其宗。
Hibernate为什么如此成功?
这篇文章是Gavin King写的,非常有趣,充分体现了Hibernate的设计理念。
1、飞快的版本发布
保持活跃的开发速度,经常进行版本发布,甚至几天之内就从前一个版本开发到下一个版本。这样是保证软件远离Bug的最好的办法,也可以让用户感到很放心,确信Hibernate的开发十分活跃,另外这样做也有一大好处,就是可以发现哪些功能是用户真正需要的。
2、回归测试
我想现在整个Java社区一定都很重视自动回归测试。如果软件的功能和设计有比较大的修改,那么一个综合性的test suite对于软件可维护性和稳定性来说实在是太重要了。我们应该有这样的意识:如果对软件的一个新功能没有进行回归测试,我们根本就不该去做它。
3、把一个功能做到最好
要么不做,要做,就一定做到最好。那些我们做不到最好的功能,我们根本不去做,扔给其他软件去做吧。
4、避免过度设计
浪费大量的时间和精力进行软件功能的抽象和扩充软件的灵活性,还不如多花点时间来解决你的用户面临的实际问题呢!简单一点! 软件能跑起来就OK,不要尝试去解决你的用户根本不关心的问题。就算你的软件设计的不够优雅也没有关系,反正还是initial阶段嘛!以后再 refactor,你应该关注的问题是及时的把有用的功能给做出来。
5、集权
在你需要由民主投票来下决定之前,至少你已经把软件轮廓做好了。软件开发需要由一两个开明的人来领导,这样可以保证软件开发的连贯性而不至于产生太大的分歧,可以保证开发团队集中火力把要实现的功能做到最好。我觉得,OSS软件最大的风险就是意见不统一,摊子铺的太大,结果最后搞的什么都没有做好。
(译者按:非常赞同,凡是成功的OSS软件,都是在某个牛人已经把软件做好了之后,发布出来,然后由大家往里面添加功能的,并且在牛人的领导下不断进步。缺乏牛人的OSS软件都不算很成功,比如Mozilla)
6、文档
没有什么比文档更重要的了。如果你的用户不知道你的软件有这么一个功能,就等于没有这个功能,干脆把它去掉得了,省得给源代码增加复杂度。
7、避免标准化
好的标准可以带来软件的互用性和可移植性,坏的标准能够窒息软件创新!“支持XXX标准”根本就不是真实的用户需求,特别是当这个XXX标准是那些在其位不谋其政“所谓”的专家委员会制订出来的。(译者按:莫非指Sun,IBM等几个big name?)最好的软件是在不断的尝试,不断的出错,不断的经验积累的过程中产生的。 事实上的标准往往更加贴近用户需求。
8、10分钟之内把Hibernate跑起来
潜在的Hibernate的用户在他们下载了Hibernate,第一次使用的时候根本就不可能花半个小时那么多时间来安装、配置和 troubleshooting,他们早就丧失了对Hibernate的兴趣了。我们的口号就是新用户(假设有足够的JDBC知识)5分钟之内把 Hibernate的Demo跑起来,而他们能够在1个小时之内写出“Hello World”式的最简单的Hibernate程序并且正常运行。
9、开发人员的责任感
用户总是不可避免的碰到问题,开发团队有责任有义务提供帮助。用户让我们知道了文档的漏洞,用户让我们知道了测试用例的小bug。此外,没有用户来用我们的Hibernate,我们还开发它做什么,不是浪费时间吗!
10、易用的、可更新的wiki网页
(译者按:cowiki是Hibernate网站用的一个网站内容发布软件)