Java数据对象(Java Data Objects,JDO)是一个应用程序接口(API),它是Java程序员能够间接地访问数据库,也就是说,不需使用直接的结构化查询语言(SQL)语句。JDO是作为Java数据库连接(JDBC)的一个补充来介绍的,而JDBC是一个支持使用SOL语句对流行的数据库程序进行访问的接口。有了JDO,程序员就可以使用类来定义数据对象,然后支撑程序就会根据类的定义来管理对给定数据库的实际的数据访问了。  

JDO是以Sun公司为首所制定的Java Community Process(Java标准制定组织,JCP)的一部分。JDBC仍然保留使用是因为它比起JDO允许程序员在数据库访问上有更大的控制权。除JDO和JDBC外的另一个选择是Enterprise JavaBeans (EJB)。

一、为什么要用JDO

Java开发人员已经有好几种存取数据库的方法:序列化,JDBC,面向对象映射工具,面向对象数据库,以及实体EJB。那为什么还要介绍其他的存储架构呢?答案是,上面每一种实现存储的方案都存在一定的限制。JDO正在尝试解决这些限制。

序列化: 是Java建立的一种传输机制,它能够把对象的信息转换成一系列的字节码,这些字节码可以被传输到网络或者存储到一个文件中。序列化的使用非常简单,但他还是有限制的。它必须立即存取对象的特征,而且它不适合存取大批量的数据。在更改一个对象的属性时如果有错误发生它无法实现“回滚”,因此不适于应用程序对数据完整性的要求,而且不能实现多个线程或程序异步读写数据。所有这些不足都使得序列化无法满足大多数数据存储要求。

JDBC:许多程序员使用 JDBC API来操作关系数据库。JDBC克服了许多序列化中存在的缺点:它可以操作大批量的数据,有确保数据一致性的机制,支持信息的并发存取,可以使用已经非 常成熟的SQL语言。不幸的是,JDBC使用起来并不像序列化那么简单。JDBC使用的关系范例无法用于存储对象,因此你不得不放弃在代码中使用面向对象 原则存储数据。

面向对象映射工具:由软件厂商创建的架构可以为你实现对象和关系数据库之间的映射。 这种对象-关系映射支 持使你专注于对象模型的设计而不必关心面向对象和关系数据库之间的匹配。不幸的是每一种对象-关系映射产品都有一套他自己厂商实现的标准。你不得不使自己 的代码迁就于某一个单独厂商的实现。假如这个厂商提高产品价格或者停止对bug更改的支持,使你准备放弃它而用其他的厂商实现架构时,你就必须重写你的代 码。

面向对象的数据库:比对象关系数据库映射更好的选择使使用一些软件厂商开发了一种新的把对象存储到数据库的方法。这种面向对象的数据库使用起来常常比对象关系映射软 件简单。ODMG组织成立的目的之一就是创建一种访问对象数据库的标准API。多数厂商都遵崇ODMG组织的要求,因此由于厂商实现不同带来的麻烦也解决 了。但是,一些企业对于从关系数据库转向对象数据库显得犹豫不决,因为有大量的数据存储在传统的关系数据库中。虽然一些数据库分析工具可以用于面向对象数 据库与关系数据库之间的移植,然而大量的数据存储使用的仍然是关系数据库。

实体EJB:Java平台的企业级应用中引入了实体EJB。 实体EJB是一个组件,他描述了数据库中的持久性数据信息。EJB使用类似于对象-关系映射的办法,它提供了一个持久性数据的面向对象的表示。不同于对象关系软件,EJB对于关系数据库没有限制;它描述的持久性信息可以来自一个企业信息系统(EIS) 或者其他的存储设备。而且,EJB要求遵循一个严格标准,实现它的厂商必须遵循这个标准。不幸的是,EJB标准在面向对象方面稍微有些欠缺,比如一些高级 的特性:继承、多态和复合关系等。另外,EJB的代码编写很复杂,而且它是一个重量级组建需要消耗应用服务器很多的资源来运行。但是,EJB中的会话 Bean和消息驱动Bean有很多优势,所以JDO规范详细定义了JDO如何与他们进行集成。

JDO:JDO集成了很多上述持久性 机制的特性,这使得在JDO中创建一个持久化(persistence)类就像创建一个序列化类一样简单。JDO支持批量数据的存储,数据一致性,并发处 理和JDBC的查询功能。就像对象-关系映射软件和对象数据库一样,它允许使用面向对象的高级特性比如“继承”。它避免了像EJB中实体Bean一样必须 依赖于来自厂商定义的严格规范。同EJB一样,JDO也不规定任何特定的后端数据库。

但是,这里还是要说一下,世界上没有“万灵丹”。所以,使用JDO并不是对于每一个应用程序都是有好处的。很多应用程序完全可以使用其他更理想的存储机制。

二、JDO架构

下面我开始对JDO的架构作一个简单的介绍。

下图显示了JDO架构主要的几部分:

JDOHelper :javax.jdo.JDOHelper类拥有一些静态的助手(helper)方法。这个方法可以获得一个持久对象的生命周期还可以用来创建一个与具体 实现厂商无关的PersistenceManagerFactory的实例,这里使用了工厂(factory)模式。

PersistenceManagerFactory:javax.jdo.PersistenceManagerFactory类可以通过JDOHelper类的助手方法获得,这是一个标准的工厂类,他可以创建PersistenceManager类。

PersistenceManager:javax.jdo.PersistenceManager接口是应用程序经常要使用的一个主要的JDO接口。每 一个PersistenceManager负责控制一组持久化对象而且他还可以创建新的持久化对象或删除现有的持久化对象。Transaction和 PersistenceManager之间存在这一对一的关系,同时PersistenceManager又是Extent和Query的工厂类,也就是 说这两个对象可以通过PersistenceManager创建。

PersistenceCapable:用户定义的持久化类都必须扩展实现PersistenceCapable接口。大多数JDO实现的供应商都提供一 种“增强器”(enhancer)的功能,它可以向你要实现的持久化类中增加PersistenceCapable接口的实现。也就是说,其实你根本不会 自己去实现这个接口。

Transaction:每一个PersistemceManager和javax.jdo.Transaction都是一一对应的。Transactions用来处理事务,它使得持久化数据可以成批的一次性添加到数据表中,如果出现异常就将数据回滚。

Extent:java.jdo.Extent是映射数据库中具体表的类的一个逻辑视图。Extent可以拥有自己的子类,它通过PersistenceManager获得。

Query:java.jdo.Query接口用具体的厂商JDO来实现,它负责处理JDO查询语言(JDOQL),这些JDOQL最终被解释为实际的数据库SQL语言。同样这个接口也是通过PersistenceManager获得的。

下面的例子显示的JDO接口如何操作并执行一个查询并更新持久化对象。

例子:JDO接口的交互

//通过助手类获得PersistenceManagerFactory

PersistenceManagerFactory factory=

JDOHelper.getPersistenceManagerFactory(System.getProperties());

//通过PersistenceManagerFactory获得PersistenceManager对象

PersistenceManager pm=factory.getPersistenceManager();

//创建并开始一个事务

Transaction tx=pm.currentTransaction();

tx.begin();

//查询employee表中每周工作时间大于40小时的研究人员

Extent ex=pm.getExtent(Employee.class,false);

//获得一个Query

Query query=pm.newQuery();

//设置这个query作用的范围,即查询的是那个表或记录集

query.setCandidates(ex);

query.setFilter(division.name == /Research/ + && avgHours > 40);

Collection result=(Collection)query.execute();

Employee emp;

for(Iterator itr=result.iterator();itr.hasNext();){

emp=(Employee)itr.next();

emp.setSalary(emp.getSalary()*2);

}

//提交记录释放资源

tx.commit();

pm.close();

factory.close();

上面的代码片断包括了JDO几个主要的接口,在此你可以对JDO各个接口的使用方法有一个粗略的印象,以后实际的应用中JDO接口也都是这样使用的。

三、JDO的异常

JDO不会抛出通常的运行时异常,比如NullPointerExceptions、 IllegalArgumentException等它只抛出JDOException异常。JDOExcetion的结构如下图所示,这是一个继承的层 次结构,从他们的字面含义就可以看出它们的用途,在这里就不详细说了,要想了解JDO异常的层次结构可以参考它们的JavaDoc。

四、使用JDO的好处

  ·简便性(Portability):使用JDO API编写的程序可以在不同开发商的多种可用的实现上运行,不用修改一行代码,甚至不用重新编译。

  ·透明地访问数据库(Transparent database access):应用程序开发者编写代码透明地访问底层数据存储,而不需要使用任何数据库特定代码。

  ·易用性(Ease of use):JDO API允许开发者只需要关注他们自己范围内的数据模型(Domain Object Model,DOM),而持久化的细节就留给JDO实现。

  ·高性能(High Performance):Java应用程序开发者不需要担心数据访问的性能优化,因为这个任务已经委派给了JDO实现,它通过改善数据访问的模式以获得最佳性能。

  ·和EJB集成(Integration with EJB):应用程序可以利用EJB的特征,例如远程信息处理、自动分布式事务协调和贯穿整个企业级应用使用同样的DOMs实现安全性。

五、使用JDO,vs. EJB和JDBC

  JDO并 不意味着要取代JDBC。它们是两种以各自独一无二的能力互相补充的技术,具有不同技术背景和开发目的开发者可以使用二者中的一个。例如。JDBC通过直 接的数据库访问控制和缓存管理,提供给开发者更大的弹性。JDBC是一种在工业界被广泛认可的成熟技术。另一方面,JDO,通过隐藏SQL提供给开发者更 大的简便性。它将Java平台开发者从必须熟悉或学习SQL中解脱出来,而将精力集中在DOM上,同时JDO管理在持久存储中对象存储的字段到字段的细 节。

  JDO被 设计成EJB的补充。CMP为容器提供简便的持久化,而JDO可以以两种方式集成到EJB中:(1)通过会话Bean,它含有JDO Persistence-capable类(会话Bean的持久化助手类)用来实现依赖对象;(2)通过实体Bean,它含有被用作BMP和CMP代理的 JDO Persistence-capable类。

  你可以学习更多关于JDO和JDBC之间的关系,还有EJB2.0 CMP和JDO之间的关系。

六、POJO之路

  JDO和 EJB之间在持久化模型上显著的差别曾经在开发者中间引起了混乱。作为回应,Sun微系统正领导一个社区项目为Java技术社区创建POJO持久化模型。 这个项目在JSR-220的赞助下执行,由Linda DeMichiel领导。JDO2.0(JSR-243)的专家组成员被邀请加入到EJB3.0(JSR-220)专家组中。

  创建POJO持久化模型的目的是为所有使用Java SE和Java EE平台的Java应用程序开发者提供一个对象—关系(object-relational)映射工具。值得注意的是Oracle正以co-specification lead的身份加入到Sun EJB3.0。EJB3.0的公众评论草案已经可以得到。

  JSR-243(JDO2.0)遵循了那些来自于JSRs220和243规范的领导写给Java技术社区的信件所描述的轮廓。

  JDO2.0并不打算作为EJB3.0持久化特定API的集中,而是作为JDO1.0.2的发展。但是JDO的POJO持久化模型和EJB3.0之间的类似处,使得JDO的客户当使用JDO2.0满足立即的需求时,可以很容易的接受EJB3.0持久化模型。另外,JSR-243打算将JDOQL用作一种关于EJB3.0持久化数据的可选查询语言。这种语言了已经被更新从而可以更好地对EJB3.0使用。

  要了解更多关于持久化模型的知识,请查看EJB/JDO持久化FAQ。

七、JDO Class类型

  在JDO中一共有三种类型的类:

  ·Persistence-capable:这种类型代表那些实例可以被持久化到一个数据存储中的类。请注意,这些类在JDO环境中被使用之前,需要通过JDO元数据规范进行加强。

  ·Persistence-aware:这些类操纵persistence-capable类。JDOHelper类包含了一些方法,它们允许询问一个persistence-capable类的实例的持久化状态。请注意,这些类使用最小化的JDO元数据加强。

  ·Normal:这些不可被持久化,并且对持久化一无所知。另外它们不需要JDO元数据。

八、JDO实例的生命周期

  JDO管理一个对象从创建到删除的生命周期。在它的生命周期,JDO实例不断地转换它的状态,直到最后被Java虚拟机(JVM)作为垃圾回收。状态的转换使用PersistenceManager类的方法完成,包括TransactionManager——例如makePersistent()、makeTransient()、deletePersistent()——和提交或者回滚更改。

  表1显示JDO规范定义的10种状态。前面的七种是必须的,后面的三种是可选的。如果一个实现不支持某些操作,那么就不会获得三种可选的状态。

表1 JDO生命周期

状态 描述
Transient 任何使用开发者定义的构造函数创建的对象,都不包括持久化环境。一个瞬时实例没有JDO身份。
Persistent-new 被应用程序组件请求的任何对象都变为持久的,通过使用PersistenceManager类的makePersistent()。这样的一个对象将会拥有一个分配的JDO身份。
Persistent-dirty 在当前事务中被改变的持久对象。
Hollow 代表在数据存储中特定数据的持久对象,但是在它的实例中没有包含值。
Persistent-clean 代表在数据存储中的特定事务数据的持久对象,并且它们的数据在当前事务处理中还没有被改变。
Persistent-deleted 代表在数据存储中的特定数据的持久对象,并且在当前事务处理中已经被删除。
Persistent-new-deleted 在同一个事务处理中最近被持久化和删除的持久对象。
Persistent-nontransactional 代表数据存储中的数据的持久对象,当前它们的值已经被装载,但是还没有事务处理一致。
Transient-client 代表一个瞬时事务处理实例的持久对象,它们的数据在当前事务中还没有被改变。
Transient-dirty 代表一个瞬时事务处理实例的持久对象,它们的数据在当前事务中已经被改变。

图2显示了JDO实例各状态之间的转换。

  本文稍后的代码片断,将示范如何执行我们刚刚讨论的操作。

九、JDO参考实现

  JDO参考实现,来自于Sun微系统,已经可用,一同发行的还有一种被称为fstore的基于文件的存储机制。Sun已经把JDO捐献给开源社区。JDO1.0和JDO2.0将会作为Apache JDO项目的一部分进行开发。但是由于时间的限制,JDO2.0的参考实现并不是作为Apache项目建立的,而是作为一个JPOX 发行。一些商业实现也是可用的。

十、JDO编程模型

  JDO定义了两种类型的接口:JDO API(在javax.jdo包中)和JDO服务提供者接口(SPI)(在javax.jdo.spi包中)。JDO API面向应用程序开发者,而JDO SPI面向容器提供者,和JDO卖主。

  一个应用程序包含两个主要的接口:

   ·PersistenceManagerFactory代表了应用程序开发者用来获得PersistenceManager实例的访问点。这个接口的实 例可以被配置和序列化以备后来使用。然而,需要注意的是,一旦第一个PersistenceManager实例从 PersistenceManagerFactory中被获得,这个工厂就不再是可配置。你可以使用下面的代码来获得 PersistenceManagerFactory。

// 为JDO实现和数据存储设置一些属性
Properties props = new Properties();
props.put(...);
// 得到一个PersistenceManagerFactory
PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory (props);

·PersistenceManager是JDO-aware应用部分的主要接口。它提供了方法来持久化一个对象,也可以重新得到持久对象和将它们从持久存储中移除。可以使用下面的方法获得PersistenceManager。

PersistenceManager pm = pmf.getPersistenceManager ();

一旦获得了PersistenceManager对象后,应用程序就可以一些任务,例如:持久化一个对象、从持久数据中获得一个对象、从持久数据中删除一个对象、更新一个对象等等。

接下来的代码片断示范了如何持久化一个对象,它更新一个对象的状态从Transient到Hollow。

Employee emp = new Employee("Sarah Jones", 23, 37000.00);
Transaction tx;
try {
tx = pm.currentTransaction();
tx.begin();
pm.makePersistent(emp);
tx.commit();
} catch (Exception e) {
if(tx.isActive()) {
tx.rollback();
}
}

从持久数据中获得一个对象同样简单,你可以使用Extent(一个信息的持有者)或者Query(提供了更精确的过滤)。下面是一个使用Extent的例子:

try {
tx = pm.currentTransaction();
tx.begin();
Extend ex = pm.getExtent(Employee.class, true);
Iterator i = ex.iterator();
while(i.hasNext()) {
Employee obj = (Employee) i.next();
}
tx.commit();
} catch (Exception e) {
if(tx.isActive()) {
tx.rollback();
}
}

最后,从持久数据中删除一个对象也可以简单完成,首先获得一个从持久数据中获得一个对象,然后调用deletePersistent(obj)方法。

十一、查询对象

JDO规范要求开发商必须提供使用JDOQL的查询能力,JDOQL是一种面向围绕被持久化对象的查询语言。PersistenceManager类定义了构造Query实现类的实例的方法。一个查询过滤器可以被指定为一个布尔表达式,就像SQL的布尔操作符。

生命周期开发:在你的应用程序中使用JDO

可以通过以下六个步骤建立一个JDO应用:

1. 设计你的范围内的将会正常使用的类。对一个要求持久化的类的唯一要求就是它要有一个默认构造函数,访问权限可能是private。

2. 使用元数据定义持久化定义:在这个步骤中,你编写元数据,指定那些类和字段应该被持久化等等。这个文件可以包含对于一个类或一个或者多个包含持久类的包的 持久化信息。一个类的元数据文件的名称是这个类的名字加上“.jdo”后缀,注意,这个文件必须放在和.class文件相同的目录中。对于整个包的元数据 文件的必须包含在一个称作package.jdo的文件中。元数据文件可以使用XDoclet或手动开发。下面是一个简单的对于两个类的元数据文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jdo SYSTEM "jdo.dtd">
<jdo>
<package name="com.xyz.hr">
<class name="Employee" identity-type="application" objectidclass="EmployeeKey">
<field name="name" primary-key="true">
<extension vendor-name="sunw" key="index" value="btree"/>
</field>
<field name="salary" default-fetch-group="true"/>
<field name="dept">
<extension vendor-name="sunw" key="inverse" value="emps"/>
</field>
<field name="boss"/>
</class>

  <class name="Department" identity-type="application" objectidclass="DepartmentKey">
<field name="name" primary-key="true"/>
<field name="emps">
<collection element-type="Employee">
<extension vendor-name="sunw" key="element-inverse" value="dept"/>
</collection>
</field>
</class>
</package>
</jdo>

3. 编译这些类,并且使用JDO加强器来加强它们。任何persistence-capable类的实例在被JDO持久化引擎管理之前必须被加强。JDO字节 码加强器通过对类定义特定的改变来装换这个类,使得任何持久实例可以和数据存储中的数据描述保持同步。和参考实现一起发行的JDO加强器,能够从Sun微 系统得到,可以使用如下的方式运行:

prompt> java -classpath
%JDO-HOME%/lib/jdo.jar;%JDO-HOME%/lib/jdori.jar;
%JDO-HOME%/jdori-enhancer.jar com.sun.jdori.enhancer.Main -d
/enhanced -s . -f path/tp/package.jdo path/to/theclasses.class

注意:对JDO加强器最重要的参数是一个.jdo文件的名字和.class文件的名字。另外,

·-d选项指定输出文件的目标文件夹;

·-s选项指定jdo和class文件的源文件夹;

·-f选项强制重写输出文件。

如果忽略这个步骤,那么当你运行应用程序和持久化一个对象时将会抛出ClassNotPersistenceCapableException异常。

4. 为被持久化的类建立数据库表。如果你已经有了一个数据库方案,那么这一步是可选的。基本上,你必须建立表、索引和在JDO元数据文件中为类定义的外键。有些JDO实现包含一个方案工具,可以根据JDO元数据文件产生所有的这些东西。

5. 编写代码来持久化你的对象。在这个步骤中,你要指定那些类在什么时间被实际持久化。正如前面提到的,最初的步骤是获得一个PersistenceManager的使用权。

6. 运行你的应用程序。使用java命令,并且包含必要的.jar文件在你的classpath中。

java学习之JDO相关推荐

  1. 转:又一篇“java学习路线图”

    转自:http://hi.baidu.com/clebean/blog/item/cdab34da86055ed7b7fd482d.html 仅供参考! 在开始之前有必要再讨论一下J2ME,J2SE, ...

  2. 推荐几个java学习网站

    推荐几个java学习网站 Java代码查询站点 S+/s4hh@k   1. java2s http://www.java2s.com/ PeYmf1ox   这个网站非常好,分成三大类,分别是Exa ...

  3. Java学习路线图,如何学习Java事半功倍?

    作为一个初学者想掌握Java并不是很容易,Java本身是具有一定难度的,虽然说兴趣这东西可以让我们学习不累,但是有多少人学习是因为兴趣,或者有多少人知道自己的兴趣在哪?所以我很明确的告诉你学习这事本来 ...

  4. Java学习必不可少的网站,快收藏起来

    java技术在IT互联网行业的发展前景一直在提升,越来越多的人都在学习java技术,今天小编来给大家提供一些学习Java的网站集合,希望能够帮助到正在学习java技术的同学. Java学习必不可少的网 ...

  5. 分享五款java学习辅助工具,总有你用的上的~

    想要学好java技术,除了自身的努力,辅助工具也不缺少,辅助工具可以帮助大家在今后的工作中可以提高工作效率,下面小编就来分享五款java学习辅助工具,总有你用的上的~ 五款java学习辅助工具: 1. ...

  6. Java学习从入门到精通的学习建议

    想要学好java技术,首先打好基础很重要,不论学什么基础都是重中之重,学习Java更是如此.如:基础语法.核心类库.面向对象编程.异常.集合.IO流等基础如果学不好,那么后边更深入的语法也不容易学会. ...

  7. java学习笔记11--Annotation

    java学习笔记11--Annotation Annotation:在JDK1.5之后增加的一个新特性,这种特性被称为元数据特性,在JDK1.5之后称为注释,即:使用注释的方式加入一些程序的信息. j ...

  8. java学习笔记13--反射机制与动态代理

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note13.html,转载请注明源地址. Java的反射机制 在Java运行时环境中,对于任意 ...

  9. JAVA学习资源网站

    中文java技术网--http://www.cn-java.com/ 灰狐动力(http://www.huihoo.com/)-- 该站点有许多的开源的项目的介绍和学习,涉及操作系统,数据库等许多方向 ...

最新文章

  1. VGG16之特征提取和网络参数的查看(偏置和权重)(这里只做简单介绍)
  2. 数据结构和算法:第八章 图论算法
  3. 如何正确使用穿线管 穿线管布局解析
  4. 常用计算机服务,常用计算机端口对应的服务(The commonly used computer port corresponding service).doc...
  5. 区块链随想:共识不等于信用
  6. linux下mysql数据库操作命令
  7. 超图Cesium二三维切换
  8. 如何用1年时间获得3年成长?
  9. 微信小程序css篇----flex模型
  10. 编译carrot2发布
  11. Sample Science 909 Lab for Mac - 909鼓声虚拟乐器
  12. 使用Lua GD库动态生成验证码图片(2)
  13. baseservlet怎么写_BaseServlet
  14. 用Java代码编程实现模拟机器人对话
  15. 基于深度学习和光流的地铁乘客上下车自动检测算法
  16. TDM-GCC MINGW配置与优化算法测试函数使用
  17. MATLAB安装文件的目录
  18. Matlab 数字图像处理 频域滤波函数paddedsize
  19. 弹性地基梁计算程序 注册机_弹性地基梁计算程序是怎样的? 弹性地基梁几种计算方法的分析比较...
  20. solomn数据集的分布情况简介

热门文章

  1. -tomcat的介绍
  2. 为什么有些30岁的程序员代码敲着敲着就创业了
  3. 房贷压力那么大,当房奴那么累,为什么很多年轻人还贷款买房?
  4. 笔记本ssd固态硬盘的M.2、SATA、PCI-E和NVMe的区别
  5. K3 wise 老单增加自定义项为下推或上拉【选单条件】
  6. 【图像处理】图形图像中术语
  7. attiny13a程序实例_关于ATtiny13A的程序
  8. CE下中文输入法编辑器(转)
  9. 修改 oracle 字符 zhs,修改Oracle数据库的字符集(UTF8→ZHS16GBK)
  10. html文件访问遭拒,防止IE中出现“ SCRIPT5:访问被拒绝”错误