hibernate 数据源层-O/R Mapping

时间:2021-11-23 16:36:49
  
数据源层-O/R Mapping
主要介绍三层架构,如何分层?(逻辑上的分层,二个原则)
数据层技术的选择:直接使用
SQL/JDBC
优点:很多开发者熟悉关系数据库管理系统,理解SQL,也知道如何使用表和外键进行工作。此外,他们可以始终使用众所周知并广泛使用的DAO设计模式对业务逻辑隐藏复杂的JDBC代码和不可移植的SQL。
缺点:为域中的每个类手工编写持续性代码的工作是非常可观的,特别是需要支持多种SQL方言时。这项工作通常会消耗很大一部分的开发努力。此外,当需求改变时,一个手工编码的解决方案总是需要更多的注意和维护努力。
 
序列化:Java有一个内建的持久化机制:序列化提供了将对象图(应用状态)写到字节流中的能力,然后它可能被持久化到文件或数据库中。持久化也被Java的远程方法调用(RMI)使用来为复杂对象传递值语义。持久化的另一种用法是在机器集群中跨节点复制应用状态。
缺点:很不幸,一个相互连接的对象图在序列化之后只能被当作一个整体访问,如果不反序列化整个流就不可能从流中取出任何数据。这样,结果字节流肯定会被认为不适合进行任意的检索或聚合。甚至不可能独立地访问或更新一个单独的对象或子图。
非常明显,因为当前特定的技术,序列化不适合于作为高并发性的Web和企业应用的持久化机制。在特定的环境中它被作为桌面应用的适当的持久化机制。
 
EJB entity beans
EJB1.1实体Bean在实践中彻底地失败了。EJB规范的设计缺陷阻碍了Bean管理的持续性(BMP)实体Bean有效地执行。在EJB1.1许多明显的缺陷被纠正之后,一个边缘的稍微可接受的解决方案是容器管理的持续性(CMP)。然而,CMP并不能表示一种对象-关系不匹配的解决方案。
CMP缺点:
¨ CMP实体Bean的粒度既太粗又太细:CMP Bean与关系模型中的表是按照一对一的方式定义的。这样,它们的粒度过粗,不能够完全利用Java丰富的类型。
¨ 虽然EJB可以利用继承实现,但实体Bean并不支持多态的关联和查询
¨ 不管EJB规范所宣称的目标,实体Bean实际上是不可移植的。CMP引擎的性能因厂商而异,并且映射元数据也是高度特定于厂商的。
¨ 实体Bean不可序列化。我们发现当我们需要将数据传输到远程客户层时,我们必须定
义额外的数据传输对象(DTO,也被称作值对象)
¨ 实体Bean必须依赖于EJB容器测试困难。
 
JDO、Object-oriented database systems
大多数面向对象的数据库系统对ODMG标准都提供了许多程度的支持,但据我们所知,还没有完全的实现。此外,在规范发布以后的很多年,甚至到了3.0版,还是感觉不太成熟,并且缺乏很多有用的特征,特别是基于Java环境的。ODMG也不再活跃。最近,Java数据对象(JDO)规范(发表于2002年4月)揭开了新的可能性。JDO由面向对象数据库团体的成员驱动,除了对现有的ODMG的支持之外,面向对象的数据库产品现在还经常将其作为主要的API采用。
JDO 的优点在于它很简单。开发人员使用 Java 语言持久存储对象实例并从存储器检索实例。处理逻辑、同步和故障转移等均被透明地处理。开发人员无需使用 SQL 或 Java 语言提供的不便的序列化机制,只使用 POJO(无格式普通 Java 对象)即可,利用 JDO 接口将对象引用传递到存储器中并从存储器检索对象引用。
 
O/R Mapping
 
什么是O/R Mapping?它有什么优点?
简单地说,对象-关系映射就是Java应用中的对象到关系数据库中的表的自动的(和透明的)持久化,使用元数据(meta data)描述对象与数据库间的映射。本质上,ORM的工作是将数据从一种表示(双向)转换为另一种。
提高生产率(Productivity
与持久性有关的代码可能是Java应用中最乏味的代码。Hibernate去掉了很多让人心烦的工作(多于你的期望),让你可以集中更多的精力到业务问题上。不论你喜欢哪种应用开发策略——自顶向下,从域模型开始;或者自底向上,从一个现有的数据库模式开始——使用Hibernate和适当的工具将会减少大量的开发时间。
 
可维护性(Maintainability
   减少了代码,重构更方便,提高了可维护性。ORM是对象和关系数据库之间的缓冲区,用来很好的将他们隔离。
 
更好性能(Performance
ORM软件的实现人员可能有比你更多的时间来研究性能优化问题。你知道吗,例如,缓存PreparedStatement的实例对DB2的JDBC驱动导致了一个明显的性能增长但却破坏了InterBase的JDBC驱动?你了解吗,对某些数据库只更新一个表中被改变的字段可能会非常快但潜在地对其它的却很慢?在你手工编写的解决方案中,对这些不同策略之间的冲突进行试验是多么不容易呀?
 
厂商独立性(Vendor independence
ORM抽象了你的应用使用下层SQL数据库和SQL方言的方式。如果工具支持许多不同的数据库(dialect),那么这会给你的应用带来一定程度的可移植性。你不必期望可以达到“一次编写,到处运行”,因为数据库的性能不同并且达到完全的可移植性需要牺牲更强大的平台的更多的力气。然而,使用ORM开发跨平台的应用通常更容易。即使你不需要跨平台操作,ORM依然可以帮你减小被厂商锁定的风险。另外,数据库独立性对这种开发情景也有帮助:开发者使用一个轻量级的本地数据库进行开发但实际产品需要配置在一台不同的数据库上。
 
如何做对象-关系数据库映射?(最后引入Hibernate)
public class User {
       private Long id;
       private String name;
       private List address;
………
}
 
create table tbl_user (
       id bigint not null auto_increment,
       name varchar(255),
       primary key (id)
)
 
Java
数据库
类的属性(基本类型)
表的列
1:n/n:1
外键
n:m
关联表
继承
单表继承、具体表继承、类表继承
 
1、 Java基本类型-表的
 
2、 Java类的映射
 
3、 关联的映射:例如一个User有多个Address,User和Address管理,User删除时,相应的Address也应该删除。
 
对象-关系的不匹配范式(paradigm)
1、 粒度(granularity)的问题。
  
增加一种新的数据类型,将Java地址对象在我们的数据库中保存为单独的一列,听起来好像是最好的方法。毕竟,Java中的一个新的地址类与SQL数据类型中的一个新的地址类型可以保证互用性。然而,如果你检查现在的数据库管理系统对用户定义列类型(UDT)的支持,你将会发现各种各样的问题。
 
2、 子类型(subtypes)的问题。
   子类型不匹配是指Java模型中的继承结构必须被持续化到SQL数据库中,而SQL数
据库并没有提供一个支持继承的策略。如何解决多态?
 
3、 同一性(identity)的问题
Java对象定义了两种不同的相等性的概念:
■ 对象同一性(粗略的等同于内存位置的相等,使用a==b检查)
■ 通过equals()方法的实现来决定的相等性(也被称作值相等)
另一方面,数据库行的同一性使用主键值表示。主键既不必然地等同于“equals()”也不等同于“==”。它通常是指几个对象(不相同的)同时表示了数据库中相同的行。而且,为一个持续类正确地实现equals()方法包含许多微妙的难点。
 
4、 与关联(associations)有关的问题
面向对象的语言使用对象引用和对象引用的集合表示关联。在关系世界里,关联被表示为外键列,外键是几个表的键值的拷贝。这两种表示之间有些微妙的不同。
5、 对象结构导航的问题
在Java中访问对象的方式与在关系数据库中有根本的不同。在Java中,访问用户的账单信息时,你调用aUser.getBillingDetails().getAccountNumber()。这是最自然的面向对
象数据的访问方式,通常被形容为遍历对象图。根据实例间的关联,你从一个对象导航到另
一个对象。不幸地是,这不是从SQL数据库中取出数据的有效方式。
为了提高数据访问代码的性能,唯一重要的事是最小化数据库请求的次数。最明显的方
式是最小化SQL查询的数量(其它方式包括使用存储过程或者JDBC批处理API)。
 
使用SQL有效地访问关系数据通常需要在有关的表之间使用连接。在连接中包含的
表的数量决定了你可以导航的对象图的深度。
性能:N+1的问题
   
 
范式不匹配的代价:
1、花费很多时间和精力来手工解决对象和关系的不匹配。
2、为了解决不匹配,甚至要扭曲对象模型直到它与下层的关系技术匹配为止
4、 JDBC API本身的问题。JDBC和SQL提供了一个面向语句(即命令)的方法从SQL数据库中来回移动数据。至少在三个时刻(Insert,Update,Select)必须指定一个结构化关系,这增加了设计和实现所需要的时间。
 
主流持久层框架纵览
目前众多厂商和开源社区都提供了持久层框架实现,常见的有:
Apache OJB(http://db.apache.org/ojb/ )
Cayenne(http://objectstyle.org/cayenne/ )
Jaxor(http://jaxor.sourceforge.net )
Hibernate(http://www.hibernage.org)
iBATIS(http://www.ibatis.com )
jRelationalFramework(http://jrf.sourceforge.net)
mirage(http://itor.cq2.org/en/oss/mirage/toon)
SMYLE(http://www.drjava.de/smyle/)
TopLink(http://otn.oracle.com/products/ias/toplink/index.html )
(其中TopLink 是Oracle 的商业产品。其他均为开源项目)
 
Apache OJB 的优势在于对各种标准的全面支持(不过事实上,我们的系统研发中并
不需要同时支持这么多标准,追求多种标准的并行支持本身也成为Apache OJB 项目发
展的沉重包袱),且其从属于Apache 基金组织,有着可靠的质量保证和稳定的发展平台。
 
Hibernate 在2003 年末被JBoss 组织收纳,成为从属于JBoss 组织的子项目之一,
从而赢得了良好的发展前景(同时荣获Jolt 2004 大奖)。
Hibernate 与OJB 设计思想类似,具备相近的功能和特色,但由于其更加灵活快速
的发展策略,得到了广大技术人员的热情参与,因此也得到了更广泛的推崇。相对Apache
OJB 迟钝的项目开发进度表,Hibernate 活跃的开发团队以及各社区内对其热烈的关注为
其带来了极大的活力,并逐渐发展成Java 持久层事实上的标准。
 
iBATIS 相对Apache OJB 和Hibernate 项目则另具特色,iBATIS 采取了更加开放式
的设计,通过iBATIS,我们可以控制更多的数据库操作细节。相对而言,Hibernate、
Apache OJB 对持久层的设计则较为封闭,封闭化的设计对持久层进行了较为彻底的封
装,从而将底层细节与上层架构完全分离,大多数情况下,特别是对于新系统,新产品
的研发而言,封闭化的设计带来了更高的开发效率和更好的封装机制,但是在某些情况
下,却又为一些必须的底层调整带来了阻力,如在对遗留系统的改造和对既有数据库的
复用上,表现出灵活性不足的弱点。此时作为OJB,Hibernate 的一个有益补充,iBATIS
的出现显得别具意义。