Java 数据对象(JDO)介绍

by
Jeff Brown, Senior Software Engineer
Object Computing, Inc. (OCI)

介绍

Java 数据对象 (JDO) is 是一个存储Java对象的规范.   它已经被JCP组织定义成JSR12规范。JDO的第一个版本在2000年6月6日提交并在2002年4月30日正式发布1.0版本规范。
规范的两个主要目的是提供数据处理和访问机制的API以及允许规范的实现作为应用服务器的一部分。

JDO 和 JDBC

JDBC和JDO都是Java调用数据库的APIs。区别在于,他们访问数据存储的具体方法不同。JDBC提供了一种非常好的机制,它可以使应用程序代码与具体的数据库厂商和数据库位置无关。在大多数情况下数据存储使用的是关系数据库。但是当使用JDBC驱动运行在一个非关系数据库时就不是很好了。而对于JDO来说,运行在它之下的数据库就可以是一个关系数据库,面向对象的数据库或者其他完全不同的数据库。在JDO运行于关系数据库之上时,它可以通过JDBC很好的完成数据存储。而这一切对于开发人员来说都是透明的,所有实现都有JDO本身来完成。

JDBC不支持面向对象的数据库表示。JDBC数据库表示完全围绕关系数据库模型。这常常导致书写代码时在应用程序和数据库之间存在一个中间层。这个层的作用也许是分解Java对象。分解Java对象的过程会对使用的对象稍作改变,这样对象才能存储到关系数据库之中。同样的必须存在一种机制来把数据库中的记录转换成适当的Java对象。JDO与JDBC刚好相反,他的数据库标示完全面向对象。这种机制并不新奇,在一些面向对象数据库中已经使用了这种机制。
JDBC的查询语言一般都是用SQL。JDO的查询语言看起来与Java更接近。使用JDO无需再专门学习一种查询语言比如SQL。如果你会用Java那么你就能够使用JDO的查询语言。

执行

JDO规范定义了JDO实现的接口已经JDO实现的内容。SUN提供了一个JDO规范的参考实现,但是在2002年5月份发布的版本中它并没有完全实现规范中所要求的内容。还有众多的厂商提供的JDO实现可以使用。在下面的表格中列出了一部分。

厂商

产品

SolarMetric

Kodo JDO

PrismTech

OpenFusion Java Data Objects

Signsoft

intelliBO

Poet

FastObjects

API

javax.jdo.spi.PersistenceCapable

任何被JDO实现控制的类都必须扩展PersistenceCapable接口。任何扩展PersistenceCapable接口的类的实例都可以看作是一个“JDO实例”。这个接口定义了JDO实现使用的方法来控制类的实例。

    public abstract javax.jdo.PersistenceManager jdoGetPersistenceManager();
public abstract void jdoReplaceStateManager(javax.jdo.spi.StateManager)
throws SecurityException;
public abstract void jdoProvideField(int);
public abstract void jdoProvideFields(int[]);
public abstract void jdoReplaceField(int);
public abstract void jdoReplaceFields(int[]);
public abstract void jdoReplaceFlags();
public abstract void jdoCopyFields(Object, int[]);
public abstract void jdoMakeDirty(String);
public abstract Object jdoGetObjectId();
public abstract Object jdoGetTransactionalObjectId();
public abstract boolean jdoIsDirty();
public abstract boolean jdoIsTransactional();
public abstract boolean jdoIsPersistent();
public abstract boolean jdoIsNew();
public abstract boolean jdoIsDeleted();
public abstract javax.jdo.spi.PersistenceCapable
jdoNewInstance(javax.jdo.spi.StateManager);
public abstract javax.jdo.spi.PersistenceCapable
jdoNewInstance(javax.jdo.spi.StateManager, Object);
public abstract Object jdoNewObjectIdInstance();
public abstract Object jdoNewObjectIdInstance(String);
public abstract void jdoCopyKeyFieldsToObjectId(Object);
public abstract void jdoCopyKeyFieldsToObjectId(
javax.jdo.spi.PersistenceCapable.ObjectIdFieldSupplier, Object);
public abstract void jdoCopyKeyFieldsFromObjectId(
javax.jdo.spi.PersistenceCapable.ObjectIdFieldConsumer, Object);

通常会有一个由JDO实现厂商提供的工具来完成普通的Java类到“JDO实例”类的转化。这个工具可能通过不同的方法来实现。第一种方法是通过字节码增强器来实现。一个JDO字节码增强器把普通的Java类转换成“JDO实例”类的过程就是把扩展PersistenceCapable接口的方法的代码加到类中。第二种方法是使用一个代码生成器,它解析现有的普通Java代码然后输出一个扩展了PersistenceCapable接口的新版本的代码。如果通过手工方式来扩展这个接口是没有好处的。

javax.jdo.PersistenceManagerFactory

PersistenceManagerFactory接口 被用来获得一个PersistenceManager 实例。这个接口中定义两个工厂方法(有关工厂方法的内容可以参考Java设计模式)。

    public PersistenceManager getPersistenceManager()
public PersistenceManager getPersistenceManager(String userid,
String password)

Because PersistenceManagerFactory is an interface, some vendor specific class, which implements this interface, must be used as a bootstrap mechanism. This should turn out to be the only vendor specific code that a JDO application uses. Because of this, the JDO specification suggests that an application level factory class be implemented which returns the appropriate instance of the PersistenceManagerFactory so that implementations may be swapped out with minimal impact on application code. Only the application's factory would need to be modified in this case.
因为PersistenceManagerFactory 是一个接口,一些实现该接口的厂商特定的类必须通过一种“自举”机制来使用。

    // SolarMetric's 实现PersistenceManagerFactory 接口的例子...
PersistenceManagerFactory managerFactory =
new com.solarmetric.kodo.impl.jdbc.JDBCPersistenceManagerFactory();
// 获得一个控制器 manager...
PersistenceManager manager = managerFactory.getPersistenceManager();

javax.jdo.PersistenceManager

The PersistenceManager interface is the primary point of contact between a Java application and the JDO implementation. Application code uses a PersistenceManager to retrieve Java objects from the data store and to add Java objects to the data store. The PersistenceManager interface also serves as a factory for several other JDO components discussed below.
PersistenceManager 接口是连接Java应用程序和JDO实现的要点。应用程序使用PersistenceManager 从数据存储中获得对象或者把一个Java对象放到数据存储中。PersistenceManager 接口也为下面将要讨论的几个JDO组件提供服务。

PersistenceManager 接口中定义了几个方法来把JDO实例对象添加到数据存储中。

    public abstract void makePersistent(Object);
public abstract void makePersistentAll(Object[]);
public abstract void makePersistentAll(java.util.Collection);

通过下面几个方法实现把JDO实例对象添加到数据存储中的过程:

    // 获得一个 manager...
PersistenceManager manager = managerFactory.getPersistenceManager();
// 下面的 Employee 必须扩展了 PersistenceCapable...
Employee newEmployee = new Employee(...);
manager.makePersistent(newEmployee);

javax.jdo.Extent

Extent (范围)对象表示所有的在当前数据库中实际的类对象。在PersistenceManager 中的一个工厂方法负责获得一个Extent (范围)对象。

    public Extent getExtent(Class persistenceCapableClass, boolean subclasses)

Class参数标明了接收的对象类型。boolean 参数标明是否包含第一个参数指定的类的子类。

Extent 接口定义了一个iterator()方法,它返回一个 java.util.Iterator来遍历所有由Extent 描述的实例。

    //获得一个 manager...
PersistenceManager manager = managerFactory.getPersistenceManager();
// the Employee class must implement PersistenceCapable...
Extent employeesExtent = manager.getExtent(Employee.class, false);
java.util.Iterator iterator = employeesExtent.iterator();

javax.jdo.Query

Query 接口允许从数据存储中获得符合某些条件的实例。Query 实例可以重载自PersistenceManager 接口中的newQuery()方法获得。
Query 接口定义了几个不同版本的重载execute() 的方法,这些方法将执行查询(Query) 并返回匹配的结果。

    // 获得一个 manager...
PersistenceManager manager = managerFactory.getPersistenceManager();
// Employee 类必须实现 PersistenceCapable接口...
Extent employeesExtent = manager.getExtent(Employee.class, false);
// 一个Query 获得所有在公司工作五年以上的 Employees....
Query query = manager.newQuery(Employee.class, employeesExtent,
"yearsOfEmployement > 5");
// 执行查询Query...
Collection employees = (Collection) query.execute();
// 处理结果...
Iterator iterator = employees.iterator();
while (iterator.hasNext()) {
Employee employee = (Employee) iterator.next();
(...)
}

注意newQuery()方法的第三个参数"yearsOfEmployement > 5"。它标明了返回结果的条件。上面的实现要求Employee 类中必须有一个属性字段叫yearsOfEmployment

试例

简介

下面的例子示范了JDO的基础应用。代码示范了如何向数据库添加数据和取回数据。所有的代码使用的都是SolarMetric's Kodo JDO实现。包括创建数据库的机制,使域对象类扩展PersistenceCapable接口的增强和厂商特定的PersistenceManagerFactory实现使用的都是Kodo JDO实现。其他的部分使用的是标准的JDO实现。

域对象

The samples will work with a small set of classes, which represent a Fleet of Vehicle objects. The two specific types of Vehicles defined are Bicycle and MotorVehicle. MotorVehicle objects have an Engine attribute.
例子是用了一个很小的类,这个类描述了一个Vehicle(交通工具) 对象的Fleet(车队)。Vehicle 定义了两个特定的对象BicycleMotorVehicle 。MotorVehicle对象有一个Engine 属性。

域对象源代码

    /**
 * Fleet.java
 */
package com.ociweb.jdodemo;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
public class Fleet {
private List vehicles = new Vector();
public void addVehicle(Vehicle vehicle) {
vehicles.add(vehicle);
}
public Iterator getVehicles() {
return vehicles.iterator();
}
public String toString() {
StringBuffer buffer = new StringBuffer("Fleet:/n");
Iterator iter = getVehicles();
while (iter.hasNext()) {
buffer.append("/t" + iter.next() + "/n");
}
return buffer.toString();
}
}
/**
 * Vehicle.java
 */
package com.ociweb.jdodemo;
public class Vehicle {
private int numberOfWheels;
public Vehicle(int numberOfWheels) {
this.numberOfWheels = numberOfWheels;
}
public int getNumberOfWheels() {
return numberOfWheels;
}
}
/**
 * Bicycle.java
 */
package com.ociweb.jdodemo;
public class Bicycle extends Vehicle {
private String model;
public Bicycle(String model) {
super(2);
this.model = model;
}
public String toString() {
return "Bike: Model " + model;
}
}
/**
 * MotorVehicle.java
 */
package com.ociweb.jdodemo;
public class MotorVehicle extends Vehicle {
private Engine engine;
public MotorVehicle(int numberOfWheels, Engine engine) {
super(numberOfWheels);
this.engine = engine;
}
public String toString() {
return "MotorVehicle With " + getNumberOfWheels()
+ " Wheels.  " + engine;
}
}
/**
 * Engine.java
 */
package com.ociweb.jdodemo;
public class Engine {
private int numberOfCylinders;
public Engine(int numberOfCylinders) {
this.numberOfCylinders = numberOfCylinders;
}
public int getNumberOfCylinders() {
return numberOfCylinders;
}
public String toString() {
return numberOfCylinders + " Cylinder Engine.";
}
}

Kodo JDO 规范

Kodo JDO包含自己的类来创建数据库模型和增强类。

模型生成工具被用于揣安数据库模型,这个模型将被用于存储JDO对象实例。工具正式支持的数据库包括:

  • DB2
  • InstantDB
  • SQLServer
  • MySQL
  • Oracle
  • PostgreSQL

其他数据库的JDBC驱动可以通过扩展代码被加入。详细内容参考Kodo JDO的文档。

模型创建工具要依赖于一个package.jdo文件,这个文件被用于定义JDO实例类的一些细节。下面的文件被用于这个例子。可以查看Kodo JDO的文档来获得文件格式和概念的详细信息。

    <?xml version="1.0"?>
<jdo>
<package name="com.ociweb.jdodemo">
<class name="Engine"/>
<class name="Vehicle"/>
<class name="Bicycle" persistence-capable-superclass="Vehicle"/>
<class name="MotorVehicle" persistence-capable-superclass="Vehicle"/>
<class name="Fleet">
<field name="vehicles">
<collection element-type="Vehicle"/>
</field>
</class>
</package>
</jdo>

schematool.bat文件被用来运行模型创建工具。.jdo文件必须作为一个参数放到命令行中。

    schematool.bat package.jdo

一旦模型被创建,域对象的类文件必须被增强以实现PersistenceCapable 接口。jdoc.bat文件被用于运行类增强器。jdoc.bat批处理文件也需要package.jdo文件作为参数方到命令行中。

    jdoc.bat package.jdo

上面演示的模型创建和类增强是Kodo JDO实现特有的,它并不是JDO规范的一部分。其他的厂商也许有他们自己的方法来完成以上部分,具体实现要参考厂商的文档。

向数据库增加数据

由于数据库已经配置完成并且我们的域对象也已经设计好了,代码也通过增强实现了PersistenceCapable接口,现在那些类的可以被实例化并添加到数据库中了。

下面的类将实例化一个Fleet,给他添加几条数据然后把它存储到数据库中。

    /**
 * SeedDatabase.java
 */
package com.ociweb.jdodemo;
// 厂商实现的PersistenceManagerFactory
import com.solarmetric.kodo.impl.jdbc.JDBCPersistenceManagerFactory;
import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;
public class SeedDatabase {
public static void main(String[] args) {
// 创建一个vehicles的fleet...
Fleet fleet = new Fleet();
fleet.addVehicle(new Bicycle("Schwinn"));
fleet.addVehicle(new Bicycle("Giant"));
fleet.addVehicle(new MotorVehicle(4, new Engine(8)));
fleet.addVehicle(new MotorVehicle(2, new Engine(4)));
fleet.addVehicle(new MotorVehicle(4, new Engine(4)));
// 获得的一个PersistenceManager...
PersistenceManager pm =
new JDBCPersistenceManagerFactory().getPersistenceManager();
// 开始一个transaction...
Transaction transaction = pm.currentTransaction();
transaction.begin();
// 存储 fleet...
pm.makePersistent(fleet);
// 提交transaction...
transaction.commit();
// 关闭 manager...
pm.close();
}
}

从数据库中获得数据

下面的代码从数据库中获得类的所有实例(包括子类的)并且把他们打引导控制台。

    /**
 * ListAll.java
 */
package com.ociweb.jdodemo;
// 厂商实现的PersistenceManagerFactory
import com.solarmetric.kodo.impl.jdbc.JDBCPersistenceManagerFactory;
import javax.jdo.Extent;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;
import java.util.Collection;
import java.util.Iterator;
public class ListAll {
public static void main(String[] args) {
// 厂商特定的工厂实现...
PersistenceManagerFactory managerFactory =
new JDBCPersistenceManagerFactory();
// 获得一个 manager...
PersistenceManager manager =
managerFactory.getPersistenceManager();
Extent ext = manager.getExtent(Vehicle.class, true);
Query query = manager.newQuery(Vehicle.class, ext, "");
Collection vehicles = (Collection) query.execute();
Iterator iterator = vehicles.iterator();
while (iterator.hasNext()) {
Vehicle vehicle = (Vehicle) iterator.next();
System.out.println("vehicle = " + vehicle);
}
manager.close();
}
}

ListAll 输出内容:

    vehicle = Bike: Model Schwinn
vehicle = Bike: Model Giant
vehicle = MotorVehicle With 4 Wheels.  8 Cylinder Engine.
vehicle = MotorVehicle With 2 Wheels.  4 Cylinder Engine.
vehicle = MotorVehicle With 4 Wheels.  4 Cylinder Engine.

限制输出的结果为有四个cylinders的Vehicle 对象。条件参数必须放到newQuery()中。
注意这个例子中使用MotorVechicle类来实例化Vechicle,因为只有MotorVehicle 对象有Engines。

    /**
 * ListFourCylinderVehicles
 */
package com.ociweb.jdodemo;
// 厂商实现的PersistenceManagerFactory
import com.solarmetric.kodo.impl.jdbc.JDBCPersistenceManagerFactory;
import javax.jdo.Extent;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;
import java.util.Collection;
import java.util.Iterator;
public class ListFourCylinderVehicles {
public static void main(String[] args) {
// 厂商特定的工厂实现...
PersistenceManagerFactory managerFactory =
new JDBCPersistenceManagerFactory();
// 获得 a manager...
PersistenceManager manager =
managerFactory.getPersistenceManager();
Extent ext = manager.getExtent(MotorVehicle.class, true);
// 只返回有4个cylinders的 vehicles...
Query query = manager.newQuery(MotorVehicle.class, ext,
"engine.numberOfCylinders == 4");
Collection vehicles = (Collection) query.execute();
Iterator iterator = vehicles.iterator();
while (iterator.hasNext()) {
Vehicle vehicle = (Vehicle) iterator.next();
System.out.println("vehicle = " + vehicle);
}
manager.close();
}
}

ListFourCylinderVehicles 的输出结果为:

    vehicle = MotorVehicle With 2 Wheels.  4 Cylinder Engine.
vehicle = MotorVehicle With 4 Wheels.  4 Cylinder Engine.

结论

JDO提供了一个数据库表示,在面向对象方面它比JDBC有何多好处。具体的对象映射和数据库厂商对于开发人员来讲都是隐藏的(换句话说开发人员根本不用管)。存储和查询的数据库操作非常简单明了。开发人员写的有关数据存储的代码非常少。有理由认为JDO对于Java数据存储是非常引人注目的技术。

参考

  • JCP - http://www.jcp.org/
  • JDO - http://access1.sun.com/jdo/
  • JDO规范- http://www.jcp.org/jsr/detail/12.jsp
  • JSR - http://www.jcp.org/jsr/overview/index.jsp
  • JDBC - http://java.sun.com/products/jdbc/
  • JDO Central - http://www.jdocentral.com/
  • Poet FastObjects JDO - http://www.fastobjects.com/FO_Products_FastObjectsj1_Body.html
  • PrismTech OpenFusion JDO - http://www.prismtechnologies.com/English/Products/JDO/index.html
  • Signsoft IntelliBO JDO - http://www.signsoft.com/en/intellibo/jdo.jsp
  • SolarMetric Kodo JDO - http://www.solarmetric.com/Software/Kodo_JDO/

Java 数据对象(JDO)介绍相关推荐

  1. Java数据对象(JDO)的前世今生

    1 Java与数据库应用,JDBC Java发明以来,在短短的几年之间,迅速占领了从桌面应用(J2SE)到 服务器 (J2EE),再到小型设备 嵌入式 系统(J2ME)的应用开发市场,其语言吸取了Sm ...

  2. java 对象数据 搜索,Java数据对象JDO 2.0查询语言的特点

    查询语言的改进是JDO2.0规范中的重要环节,本文从较高的层面阐述JDO2.0所提供的一些新功能.由于JDO2.0规范还未进入公开草案状态,目前还没有任何内容敲定下来,一切都还可能面临变化.不过,JD ...

  3. Java数据对象(JDO)的应用

    在本篇文章中,我们将详细地讨论Sun公司的Java数据对象(JDO)标准.JDO允许我们使用Java对象,支持事务和多用户.与ODBC不同的是,它使我们无需考虑SQL和与数据库有关的其他东西.它与串行 ...

  4. Java数据对象(JDO)快速入门

    JDO有一个充满活力的社区.所以如果你正在为你的POJO寻找持久化 解决方案,JDO是一个通过JCP项目开发的标准.JDO为POJO持久化提供了一个丰富和具有全部特征的JSR规范,并且很多开发商正在提 ...

  5. 数据、数据元素、数据项、数据对象的介绍和理解

    最近在读<大话数据结构>这本书 第一章上面的介绍数据结构相关概念 总结如下图: 数据结构是相互之间存在一种或多种特定关系的数据元素的集合. 对于数据 数据对象 数据元素 数据项 这四个概念 ...

  6. java 数据对象_java的几种对象(PO,VO,DAO,BO,POJO)

    一.PO persistant object 持久对象,可以看成是与数据库中的表相映射的java对象.最简单的PO就是对应数据库中某个表中的一条记录,多个记录可以用PO的集合.PO中应该不包含任何对数 ...

  7. 服务数据对象简介(Java 环境中的下一代数据编程)

    如果您认为 J2EE 编程模型和 API 迫使开发人员在特定于技术的配置.编程和调试上浪费了太多的时间,那么欢迎您阅读本文.很多 Java™ 开发人员都怀疑如何能以统一的方式访问异构的数据,并对各种提 ...

  8. java学习之JDO

    Java数据对象(Java Data Objects,JDO)是一个应用程序接口(API),它是Java程序员能够间接地访问数据库,也就是说,不需使用直接的结构化查询语言(SQL)语句.JDO是作为J ...

  9. 对象类型数据和对象实例数据_服务数据对象简介

    简而言之,SDO是用于数据应用程序开发的框架,其中包括体系结构和API. SDO执行以下操作: 简化J2EE数据编程模型 在面向服务的体系结构(SOA)中抽象数据 统一数据应用程序开发 支持和集成XM ...

最新文章

  1. 如何在Django中以GROUP BY查询?
  2. Python模型顶点法线修复
  3. akka---Getting Started Tutorial (Java): First Chapter
  4. MATLAB浮点数与十六进制(浮点数)转换
  5. c++语言中如果调用函数时,需要改变实参或者返回多个值,应该采取,2013年计算机二级C++模拟试题十一及答案...
  6. sql server2008如何修改mac地址_如何查看本机的MAC地址和IP地址?
  7. swfobject.js视频播放插件
  8. HBuilder Android真机调试
  9. CenterNet+ deepsort实现多目标跟踪
  10. 魔方——操作阶数实验
  11. MC-GAN:Multi-Content GAN for Few-Shot Font Style Transfer
  12. 词频统计(30 分)(map vector sort)
  13. SQL 格式化输出 千分位 ¥货币格式
  14. Docker安装迅雷下载工具实现远程下载
  15. android代码设置drawable,Android:Textview 通过代码设置 Drawable
  16. 华为锁屏后微信网络连接服务器,华为P30 Pro锁屏息屏状态下微信收不到信息,显示网络不可用...
  17. 喝酒神器摇骰子小程序源码分享以及搭建效果图
  18. 测测你的IQ加分析能力
  19. Serdes series # skew
  20. 网易云信圈组上线实时互动频道,「破冰」弱关系社交

热门文章

  1. php线下支付,Paypal线下支付模块,附下载地址_PHP教程
  2. butter中文意思_butter中文是什么意思(Butterfly蝴蝶和butter黄油有什么关系)
  3. Java-SpringBoot-使用SNMP对交换机/服务器进行简单的数据采集
  4. TPM零知识学习十一 —— tpm全安装流程复盘(下)
  5. Vue全家桶(前后端完全分离)
  6. Android开发之——卸载系统应用
  7. cocos2d-x 将js代码混淆成jsc
  8. 如何搭建vue脚手架
  9. 洛克希德·马丁公司的创新灵魂 和 波音的“鬼怪工厂”
  10. ZigBee、WiFi、蓝牙的区别