JDO是Java对象持久化的新的规范。JDO经SunJava Community Process认定。
一、历史
JDO是对象持久化工作的综合成果,试图提供一个对象持久化的完全版本。JDO同时继承于ODMG(对象数据管理小组,标准化对象数据库的一个独立委员会)和对象关系映射工具提供商。
JSR #000012 approved in July 1999
1999-8组建的专家小组:包括Sun、Apple、BEA、IBM、Oracle、SAP、WebGain等
2000-5 完成公开评论草案
2000-6 在JavaOne上引入
2001-3 最终草案0.93
2001-5 最终草案0.96公布
2001-6 在JavaOne上启动
2001-11 最终草案0.98
二、目标
定义对象级的持久化。
完全支持对象模型,包括引用、集合、接口、继承
完全透明持久化:这使得业务对象完全独立于任何数据库技术,这使用了一个字节码增强机制(a byte-code enhancement mechanism)。
缩短开发周期(不再需要映射)
在开发小组中清晰地划分业务人员和数据库人员。
通用持久性
JDBC限于RDBMS,JDO潜在地可以处理任何类型的数据源,包括RDBMS,ODBMS,TP监控处理,ASCII无格式文件,xml文件,properties文件,大机上的Cobol数据库,等
JDO是面向大型信息系统的一个完全的解决方案,在这样的系统中,信息存储于多种异质数据源
涵盖J2EE、J2SE、J2ME的广泛实现
强壮的事务模型
同时支持C/S和多层体系结构
三、体系
JDO 包
PersistentCapable:拥有持久实例的类必须实现这个接口。管理对象生命周期。
PersistenceManager :代表了到数据源的连接。一个应用可以打开一个或多个PersistenceManagers。
PersistenceManagerFactory:允许从数据源中得到一个PersistenceManager的实例,这个工厂也可以作为一个连接池。
Transaction:允许界定事务
Query :允许明确地声明性地使用JDO查询语言从数据源中获取数据。NB:也可以通过引用之间的基本的定位,隐含地、透明地从数据源中获取对象。
InstanceCallback:在数据库操作中(比如before/after read, before/after write,等),定义一些钩子,以做特殊处理(像暂时属性的初始化)。
JDOException:JDO操作中抛出的例外。
JDO也定义了帮助类,对象标识(由应用或数据源管理)
JDO实现可以支持或不支持兼容的PersistenceManager(当PersistenceManager是兼容的时,你可以得到存储于不同数据库的对象引用)。
NB:在JDO的第一个发布版本中,并没有严格地定义锁和锁策略。
JDO对象模型
JDO对象模型基本上是Java的对象模型,包括所有的基本类型,引用,集合和事件接口。
除了系统定义类(system-defined classes),支持所有的字段类型(包括简单型、可变和不变的对象类型〔immutable and mutable object types〕、用户定义类、数组、集合、接口)。
支持所有的成员变量修饰符(private, public, protected, static, transient, abstract, final, synchronized, volatile)
除了对象状态依赖于不可访问的或远程对象,即继承于java.net.SocketImpl、本地方法等,所有的用户定义类都可以是PersistentCapable。
JDO对象生命周期
为了能够在数据源中访问、存储对象,应用必须首先得到一个或几个数据源的连接。一个JDO PersistenceManager对象就代表了这样一个连接。它可以通过PersistenceManagerFactory类得到。持久化对象必须是实现了PersistentCapable接口的类的实例。这样的类可能同时拥有持久化的或临时的(transient)实例。
为了使一个实例持久化,编程者必须调用PersistentManager的makePersistent方法。通知JDO对象为持久化或临时的很重要,即使它们可以从JDO的行为中得到它是临时的,比如事务管理和对象标识。对象标识可以由应用管理,或者由数据源代理(这大多是在使用ODBMS实例时,因为概念ObjectID本身就是ODMG模型的一部分)。
JDO支持一种持久化模型,这这种模型中持久性自动传播到引用的对象。这种机制经常称为“延伸持久(persistence by reachability)”或者“传递持久(transitive persistence)”。这意味着一旦一个已经持久化的对象引用了一个临时对象,这个临时对象自动变成持久化的。对于JDBC编程者,这个模型可能很奇怪,但是他们会发现这是大多数情况下编程者希望从持久化框架中得到的支持。
例子:
pmf = (PersistenceManagerFactory) (Class.forName("com.libelis.lido.PersistenceManagerFactory").newInstance()); pmf.setConnectionDriverName("versant"); pmf.setConnectionURL(dbName); pm = pmf.getPersistenceManager(); tx = pm.currentTransaction(); tx.begin(); Provider aProvider = new Provider("LIBeLIS"); pm.makerPersistent(aProvider); // aProvider now persists Address anAddress = new Address("25 rue Paul Barruel", "France", "Paris"); aProvider.address = anAddress ; // anAddress now persists tx.commit(); pm.close();
对象或者通过明确的JDO查询结果从内存中得到,或者通过标准的Java对象之间的导航(navigation)得到。
最后这个机制很强大,你可以把持久对象想像为在JVM堆中的一个特殊的部分,我们称之为“客户端缓存(client cache)”。每次当你企图从一个对象导航到另一个时,如果这个对象尚不在内存中,JDO会自动从数据源中获取,并把它放在缓存中。
例子
假设aProvider对象已经装载到内存,但是它的Address对象还没有。当你写下如下代码时:
System.out.println(aProvider.address.city);
Address对象会自动装载。缓存管理自动链接到事务边界(transaction boundaries),这意味着缓存将在事务结束是刷新,所有的实体都标示为无效的。下次对象访问它们的状态时,自动地、透明地从数据源中再次装载。
例子
pmf = (PersistenceManagerFactory) (Class.forName("com.libelis.lido.PersistenceManagerFactory").newInstance()); pmf.setConnectionDriverName("versant"); pmf.setConnectionURL(dbName); pm = pmf.getPersistenceManager(); tx = pm.currentTransaction(); tx.begin(); Provider aProvider = new Provider("LIBeLIS"); pm.makerPersistent(aProvider); Address anAddress = new Address("25 rue Paul Barruel", "France", "Paris"); aProvider.address = anAddress ; tx.commit(); // objects are stored into the data source, client cache is discarded, references are invalid tx.begin(); System.out.println(aProvider); // aProvider is refreshed from the data source tx.commit(); pm.close();
每次你修改了一个对象,它在JDO缓存中对应的实体将被标示为“脏(dirty)”。
例子
tx.begin(); aProvider.address = aNewAdr; // aProvider is marked as dirty tx.commit(); // aProvider will updated in the data source
在事务的结束,PersistentManager 将把所有标示为“脏”的JDO对象(脏对象)更新到数据源中。
JDO缓存中的每一个对象都有自己的状态(实际上它们都和一个StateManager对象相关联)。并且JDO规范规定了一大堆状态和它们之间的过渡。如果感兴趣,请参照JDO规范了解详细。
NB:这些状态一般是JDO提供商关心的,而不是JDO编程者。
开发周期
为了达到上面提到的完全透明的持久化,JDO定义了一个称为“增强(Enhancement)”的字节码工具机制(byte-code instrumentation mechanism)。它的思想是从业务类中剔除所有的显式的数据库依赖代码。和已存在的或新的数据源的映射通过外部的元数据(metadata)XML文件定义。
JDO增强器读取编译的java文件(.class文件),并且应用元数据文件中定义的持久化规则。例示如下:
[[The No.1 Picture.]]
增强会添加到元数据文件描述的类的字节码中:
• 实现PersistentCapable接口的声明
• 该接口中声明的方法的字节码必须被实现
• 当修改了一个属性后该对象标示为“脏”的代码
• 需要时从数据源中获取对象的代码
• 根据元数据文件中指定的从数据源中的原始数据(raw data)到Java对象映射的代码
NB:在专家小组中,是否要把增强列入JDO规范曾经激烈争论过。一些专家认为开发者可能会被增强技术吓倒。不熟悉这个技术的开发者会惊讶于字节码增强,这是一个事实。但是增强是这样一种通用、强大的开发技术,可以在很多案例中有效地使用。开始时,每当开发者遇到一个Bug时,可能会责难增强器。我们强烈推荐增强器的“新手”仔细地看一下BCEL网站(由Source Forge开源社区提供)。在那儿,你能看到许多关于字节码增强的有用信息和工具。这种机制的熟手可以在他们的Java接口中成功地使用。所有的熟手都表现出了兴趣。
在两层(Client/Server)结构中整合
在传统的Client/Server体系中,JDO应用需要使用由JDO实现提供的PersistenceManagers把它自己连接到一个或多个数据源。
[[The No.2 Picture.]]
临时对象可以持有持久对象的引用。持久对象可以持有分布在多个PersistenceManagers中的持久对象的引用。但是这不是一个
查看本文来源