明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

Java數(shù)據(jù)對(duì)象(JDO)的應(yīng)用

[摘要]在本篇文章中,我們將詳細(xì)地討論Sun公司的Java數(shù)據(jù)對(duì)象(JDO)標(biāo)準(zhǔn)。JDO允許我們使用Java對(duì)象,支持事務(wù)和多用戶。與ODBC不同的是,它使我們無需考慮SQL和與數(shù)據(jù)庫有關(guān)的其他東西。它與串行化也有所區(qū)別,因?yàn)樗С侄鄠(gè)用戶和事務(wù)。JDO允許Java開發(fā)人員將他們的數(shù)據(jù)模型用作數(shù)據(jù)模型,無...
在本篇文章中,我們將詳細(xì)地討論Sun公司的Java數(shù)據(jù)對(duì)象(JDO)標(biāo)準(zhǔn)。JDO允許我們使用Java對(duì)象,支持事務(wù)和多用戶。與ODBC不同的是,它使我們無需考慮SQL和與數(shù)據(jù)庫有關(guān)的其他東西。它與串行化也有所區(qū)別,因?yàn)樗С侄鄠(gè)用戶和事務(wù)。JDO允許Java開發(fā)人員將他們的數(shù)據(jù)模型用作數(shù)據(jù)模型,無需在“數(shù)據(jù)端”、“對(duì)象端”之間的轉(zhuǎn)移方面花費(fèi)大量的時(shí)間。
包括CocoBase、WebGain TOPLink和Castor JDO在內(nèi)的多種產(chǎn)品都可以實(shí)現(xiàn)了JDO標(biāo)準(zhǔn)。既然有一種標(biāo)準(zhǔn)的方法,我們就可以只學(xué)習(xí)其中的一種,就象有了ODBC,我們就可以使用任何提供了驅(qū)動(dòng)程序的數(shù)據(jù)庫那樣。
在本篇文章中,我們將使用Prism技術(shù)公司的OpenFusion JDO。讀者在后面會(huì)發(fā)現(xiàn),只有很小一部分代碼使用了PrismTech API,其他部分都使用了標(biāo)準(zhǔn)的JDO標(biāo)準(zhǔn)。
創(chuàng)建Person對(duì)象
我們將首先創(chuàng)建一個(gè)Person對(duì)象,該對(duì)象遵循了JavaBean的慣例,可以對(duì)其屬性執(zhí)行g(shù)et和set操作。需要注意的是,盡管我們是在創(chuàng)建這個(gè)類,但它并沒有什么特別的,它沒有繼承或?qū)崿F(xiàn)任何基本類。對(duì)一個(gè)可保持類的要求是:
1、所有域必須能夠被JDO類訪問(public或set*方法)
2、域的數(shù)據(jù)類型必須符合JDO規(guī)格。
3、不能支持一些類型的字段(例如Thread、File、Socket等不能串行化的字段)。
下面是符合上述要求的Person.java:

public class Person {
private String name;
private String address;
private String ssn;
private String email;
private String homePhone;
private String workPhone;

// 允許我們使用構(gòu)造器創(chuàng)建Person對(duì)象
public Person(String name, String address, String ssn,
String email, String homePhone, String workPhone) {
this.name = name;
this.address = address;
this.ssn = ssn;
this.email = email;
this.homePhone = homePhone;
this.workPhone = workPhone;
}


// 方法
public String getName() { return name; }

public String getAddress() { return address; }

public String getSsn() { return ssn; }

public String getEmail() { return email; }

public String getHomePhone() { return homePhone; }

public String getWorkPhone() { return workPhone; }

public void setName(String name) { this.name = name; }

public void setAddress(String address) {
this.address = address;
}

public void setSsn(String ssn) { this.ssn = ssn; }

public void setEmail(String email) { this.email = email; }

public void setHomePhone(String homePhone) {
this.homePhone = homePhone;
}
public void setWorkPhone(String workPhone) {
this.workPhone = workPhone;
}
}
創(chuàng)建PersonPersist對(duì)象管理可保持性
現(xiàn)在已經(jīng)有了Person對(duì)象,我們需要?jiǎng)?chuàng)建一些代碼來管理這種可保持性。下面我們將詳細(xì)討論這些代碼,并學(xué)習(xí)如何:
1、初始化JDO可保持性管理器。
2、向數(shù)據(jù)庫中輸入三個(gè)人的資料。
3、從數(shù)據(jù)庫中顯示人的資料。
4、修改其中一個(gè)人的名字。
5、從數(shù)據(jù)庫中刪除一個(gè)人的資料。
6、在main()方法中進(jìn)行相關(guān)的處理。
第一步:初始化JDO可保持性管理器
我們從OpenFusion實(shí)現(xiàn)中導(dǎo)入了標(biāo)準(zhǔn)的JDO類和ManagedConnectionFactory,當(dāng)然了我們也可以將它們抽象成一個(gè)獨(dú)立的類。構(gòu)造器使用javax.jdo.PersistenceManagerFactoryClass屬性設(shè)置連接代理,這一點(diǎn)與在JDBC中設(shè)置數(shù)據(jù)庫驅(qū)動(dòng)程序的屬性很相似。
package addressbook;

import java.util.*;
import javax.jdo.*;

import
com.prismt.j2ee.connector.jdbc.ManagedConnectionFactoryImpl;

public class PersonPersist
{
private final static int SIZE = 3;
private PersistenceManagerFactory pmf = null;
private PersistenceManager pm = null;
private Transaction transaction = null;

// 需要保持的人的數(shù)組
private Person[] people;
// 現(xiàn)有對(duì)象標(biāo)識(shí)符的向量
private Vector id = new Vector(SIZE);

public PersonPersist() {
try {
Properties props = new Properties();

props.setProperty("javax.jdo.PersistenceManagerFactoryClass",
"com.prismt.j2ee.jdo.PersistenceManagerFactoryImpl");
pmf = JDOHelper.getPersistenceManagerFactory(props);
pmf.setConnectionFactory( createConnectionFactory() );
} catch(Exception ex) {
ex.printStackTrace();
System.exit(1);
}
}
連接代理是在名字為createConnectionFactory()的靜態(tài)方法中創(chuàng)建的,該代理需要JDBC URL、JDBC驅(qū)動(dòng)程序、用戶名和口令。
public static Object createConnectionFactory() {
ManagedConnectionFactoryImpl mcfi = new
ManagedConnectionFactoryImpl();
Object connectionFactory = null;

try {
mcfi.setUserName("scott");
mcfi.setPassword("tiger");
mcfi.setConnectionURL(
"jdbc:oracle:thin:@localhost:1521:thedb");

mcfi.setDBDriver("oracle.jdbc.driver.OracleDriver");

connectionFactory = mcfi.createConnectionFactory();
} catch(Exception e) {
e.printStackTrace();
System.exit(1);
}
return connectionFactory;
}


第二步:在數(shù)據(jù)庫中輸入三個(gè)人的資料

PersistPeople()使用Person.java文件中的構(gòu)造器創(chuàng)建了3個(gè)人的資料。。我們要作的第一件事是通過
getPersistenceManager()獲得一個(gè)可保持性管理器,然后創(chuàng)建一個(gè)執(zhí)行我們的任務(wù)的事務(wù)。為了保持這一對(duì)象結(jié)構(gòu)圖,我們簡(jiǎn)單地調(diào)用makePersistentAll( Object[] )方法即可。代碼底部的for()循環(huán)獲得每個(gè)保持對(duì)象的唯一的ID,并保存起來供以后使用。
public void persistPeople() {
// 創(chuàng)建人的資料的數(shù)組
people = new Person[SIZE];

// 創(chuàng)建3個(gè)人的資料
people[0] = new Person("Gary Segal", "123 Foobar Lane",
"123-123-1234", "gary@segal.com",
"(608) 294-0192", "(608) 029-4059");
people[1] = new Person("Michael Owen",
"222 Bazza Lane, Liverpool, MN",
"111-222-3333", "michael@owen.com",
"(720) 111-2222", "(303) 222-3333");
people[2] = new Person("Roy Keane",
"222 Trafford Ave, Manchester, MN",
"234-235-3830", "roy@keane.com",
"(720) 940-9049", "(303) 309-7599)");

// 保持這3個(gè)人的資料
pm = pmf.getPersistenceManager();
transaction = pm.currentTransaction();
pm.makePersistentAll(people);
transaction.commit();

// 獲取被保持對(duì)象的對(duì)象ID
for(int i = 0; i < people.length; i++) {
id.add(pm.getObjectId(people[i]));
}

// 關(guān)閉現(xiàn)有的保持性管理器,保證對(duì)象是從數(shù)據(jù)庫而不是從保持性管理器的緩存中讀取的
pm.close();
}
下面是一些可以針對(duì)保持性管理器的其他方法:
使實(shí)例成為可保持的:獲得一個(gè)臨時(shí)對(duì)象,并保持它。
刪除可保持實(shí)例:從數(shù)據(jù)存儲(chǔ)庫中刪除信息。
使實(shí)例臨時(shí)化:使實(shí)例與可保持性管理器分離,而不刪除在數(shù)據(jù)存儲(chǔ)庫中的信息。
使實(shí)例處于保持狀態(tài) 刪除保持的實(shí)例 使實(shí)例處于臨時(shí)狀態(tài)
makePersistent(Object o) deletePersistent(Object o) makeTransient(Object o)
makePersistentAll(Object[] os) deletePersistentAll(Object[] os) makeTransientAll(Object[] os)
makePersistentAll(Collection os) deletePersistentAll(Collection os) makeTransientAll(Collection os)
(這里是一個(gè)4X3的表格,可以參閱原稿中的英文表格)

第三步:顯示數(shù)據(jù)庫中人的信息
顯示信息代碼以獲得可保持性管理器開始。我們使用上面代碼中用persistPeople()方法保存的對(duì)象ID獲得對(duì)象,調(diào)用對(duì)象的方法━━在本例中是gets,來得到我們輸入的信息。我們可以發(fā)現(xiàn),要保持我們的對(duì)象,并不需要編寫大量的代碼。
public void display(int end) {
Person person;
int max = end <= SIZE ? end : SIZE;

// 獲得一個(gè)新的可保持性管理器
pm = pmf.getPersistenceManager();
// 從數(shù)據(jù)庫中獲取對(duì)象并進(jìn)行顯示
for(int i = 0; i < max; i++) {
person = (Person) pm.getObjectById(id.elementAt(i),
false);
System.out.println("Name : " + person.getName());
System.out.println("Address : " +
person.getAddress());
System.out.println("SSN : " + person.getSsn());
System.out.println("Email : " + person.getEmail());
System.out.println("Home Phone: " +
person.getHomePhone());
System.out.println("Work Phone: " +
person.getWorkPhone());
}
pm.close();
}
第四步:改變其中一個(gè)人的名字
改變存儲(chǔ)在數(shù)據(jù)庫中的一個(gè)人的信息的代碼也十分簡(jiǎn)單,它與顯示數(shù)據(jù)庫中人的信息的代碼非常類似。在這里,我們需要?jiǎng)?chuàng)建一個(gè)事務(wù)(因?yàn)橐薷钠渲械挠涗洠褂枚x的setName()方法修改一個(gè)人的名字,最終提交該事務(wù),保存所作的修改。這種操作與處理臨時(shí)對(duì)象之間真正的差別是,我們考慮是事務(wù)。
public void change() {
Person person;

// 從數(shù)據(jù)存儲(chǔ)庫中獲取對(duì)象
pm = pmf.getPersistenceManager();
transaction = pm.currentTransaction();
// 修改第二個(gè)保持記錄的DataString字段
person = (Person) pm.getObjectById(id.elementAt(1),
false);
person.setName("Steve Gerrard");
// 提交事務(wù)并關(guān)閉可保持性管理器
transaction.commit();
pm.close();
}
第五步:刪除一個(gè)人的資料
你自己能夠想象出從數(shù)據(jù)庫中刪除第二個(gè)人資料的代碼嗎?因?yàn)槲覀円呀?jīng)了解了所有編寫這一代碼所需要的知識(shí)。仔細(xì)地研究一下下面的代碼就會(huì)發(fā)現(xiàn),我們使用了第二步中的可保持性管理器方法中提到的deletePersistent()方法。
public void delete() {
// 從數(shù)據(jù)庫中獲取對(duì)象
pm = pmf.getPersistenceManager();
transaction = pm.currentTransaction();
// 從數(shù)據(jù)庫中刪除第二個(gè)人的信息,并從ID向量中刪除其ID
pm.deletePersistent(pm.getObjectById(id.remove(1),
false));
// 提交事務(wù)并關(guān)閉可保持性管理器
transaction.commit();
pm.close();
}
第六步:在main()方法中運(yùn)行上面的代碼
最后,整個(gè)代碼需要有一個(gè)main()串起來,在數(shù)據(jù)庫中輸入人的信息、改變其中一個(gè)人的名字,然后刪除該人的資料。如果運(yùn)行這一程序,就會(huì)看到程序運(yùn)行到每一步時(shí)的地址簿。
public static void main(String[] args) {
System.out.println("Create PersonPersist");
PersonPersist personPersist = new PersonPersist();

System.out.println("Setup and persist a group of people");
personPersist.persistPeople();

System.out.println("Display the persisted people");
personPersist.display(SIZE);

System.out.println("Change a name ");
personPersist.change();
personPersist.display(SIZE);

System.out.println("Delete a person ");
personPersist.delete();
personPersist.display(SIZE - 1);
}
JDOEnhancer:創(chuàng)建JDOEnhancer的JDO描述符

現(xiàn)在,我們已經(jīng)編寫好了整個(gè)應(yīng)用程序的源代碼,下一步需要作的就是創(chuàng)建一個(gè)JDOEnhancer將要使用的
JDO描述符。讀者一定會(huì)問,JDOEnhancer是什么?JDO架構(gòu)是基于下面的理念的:一個(gè)JDO實(shí)現(xiàn)能夠獲取類的字節(jié)碼,對(duì)它們進(jìn)行處理,添加一些必要的功能。例如,JDOEnhancer將使類實(shí)現(xiàn)PersistanceCapable接口(因此我們不用自己編程實(shí)現(xiàn)這一接口),而且能夠?qū)崿F(xiàn)該接口中的一些方法。因此在對(duì)代碼編譯后我們就會(huì)發(fā)現(xiàn),我們必須運(yùn)行JDOEnhancer對(duì)字節(jié)碼進(jìn)行適當(dāng)?shù)奶幚怼N覀冃枰獎(jiǎng)?chuàng)建一個(gè)給出我們需要保持的類的信息的描述符文件,這一文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jdo SYSTEM
"file:/D:/Apps/OpenFusionJDO/xml/schema/jdo.dtd">
<jdo>
<package name="addressbook">
<class name="Person" identity-type="datastore">
</class>
</package>
</jdo>
這只是一個(gè)最基本的文件,但能夠滿足我們的要求。當(dāng)然了,還有許多更復(fù)雜的映射。下面是OpenFusion例子中一個(gè)稍微復(fù)雜一些的映射:
<class name="Department" identity-type="datastore">
<field name="name"/>
<field name="employees">
<collection element-
type="com.prismt.j2ee.jdo.examples.appKeyDepartment.Employee">
</collection>
</field>
<field name="manager"/>
</class>
</package>
</jdo>
現(xiàn)在我們已經(jīng)編寫好了代碼和JDO描述符文件,我們將對(duì)它們進(jìn)行整合,并討論如何建立整個(gè)系統(tǒng)。要建立整個(gè)系統(tǒng),我們只需要簡(jiǎn)單的幾步工作即可:
1、編譯代碼。
2、運(yùn)行JDOEnhancer。
3、使用JDOEnhancer的輸出建立數(shù)據(jù)庫。
4、運(yùn)行應(yīng)用程序。
第一步:編譯代碼
我想廣大的讀者想必已經(jīng)知道如何運(yùn)行javac了吧。在運(yùn)行javac之前,我們只要保證正確地設(shè)置CLASSPATH就可以了。下面是一個(gè)在Windows平臺(tái)上運(yùn)行javac的例子:
% set OPENFUSION_DIR=D:\Apps\OpenFusionJDO
% set
CLASSPATH=%OPENFUSION_DIR%\lib\connector.jar;%OPENFUSION_DIR%\
lib\jndi.jar;%OPENFUSION_DIR%\lib\log4j.jar;%OPENFUSION_DIR%\l
ib\xerces.jar;%OPENFUSION_DIR%\lib\classes12.zip;%OPENFUSION_D
IR%\lib\jdo.jar;%OPENFUSION_DIR%\lib\jta-
spec1_0_1.jar;%OPENFUSION_DIR%\lib\ofjdo.jar;.

% javac –d . Person*.java
第二步:運(yùn)行JDOEnhancer
JDOEnhancer需要使用在上一步編譯中得到的字節(jié)碼和我們先前建立的JDO描述符文件。下面是OpenFusion JDOEnhancer的完整語法:
java com.prismt.j2ee.jdo.enhancer.JDOEnhancer

命令選項(xiàng):
-cp 開始搜索需要強(qiáng)化的類的基本路徑,與CLASSPATH不同,它是編譯后的可保持類所在的目錄
-oc 存儲(chǔ)強(qiáng)化后的類的目錄
-pd JDO描述符文件

可選項(xiàng):
-db 指定目標(biāo)數(shù)據(jù)庫 [oracle、sybase等]
-od 生成SQL腳本的目錄

下面是為建立我們的應(yīng)用程序而運(yùn)行JDOEnhancer的一個(gè)例子:
% java com.prismt.j2ee.jdo.enhancer.JDOEnhancer -oc . -pd
person.jdo -db oracle -od db -cp .
第三步:使用JDOEnhancer的輸出建立數(shù)據(jù)庫
,只要使用–db和-od可選項(xiàng),JDOEnhancer就能夠創(chuàng)建建立數(shù)據(jù)庫的數(shù)據(jù)庫腳本。它能夠創(chuàng)建許多腳本,但其中有一個(gè)的名字叫l(wèi)oad_all.sql,打開該文件并將它加載到一個(gè)SQL提示符中。(例如sqlplus for Oracle)

CREATE SEQUENCE instid_seq INCREMENT BY 1
;

CREATE TABLE JDO_addressbook_Person_SCO
(
inst_id INTEGER NOT NULL,
class INTEGER NOT NULL,
JDO_address VARCHAR2(255),
JDO_email VARCHAR2(255),
JDO_homePhone VARCHAR2(255),
JDO_name VARCHAR2(255),
JDO_ssn VARCHAR2(255),
JDO_workPhone VARCHAR2(255)
)
;
CREATE TABLE JDO_addressbook_Person
(
inst_id INTEGER NOT NULL,
class INTEGER NOT NULL,
JDO_address VARCHAR2(255),
JDO_email VARCHAR2(255),
JDO_homePhone VARCHAR2(255),
JDO_name VARCHAR2(255),
JDO_ssn VARCHAR2(255),
JDO_workPhone VARCHAR2(255)
)
;
CREATE TABLE prismjdoProp
(
name VARCHAR2(255) PRIMARY KEY,
value VARCHAR2(255)
)
;
CREATE TABLE prismjdoExtents
(
class_id NUMBER(38,0) PRIMARY KEY,
class_name VARCHAR2(255) UNIQUE,
app_key VARCHAR2(255)
)
;
ALTER TABLE JDO_addressbook_Person_SCO ADD PRIMARY KEY (inst_id, class)
;
ALTER TABLE JDO_addressbook_Person ADD PRIMARY KEY (inst_id,class)
;

INSERT INTO prismjdoExtents VALUES(0, 'addressbook.Person','com.prismt.j2ee.jdo.spi.DBKey')
;
COMMIT WORK
;

INSERT INTO prismjdoProp VALUES('USE.RDBMS.TRIGGERS', 'true')
;
COMMIT WORK
;
第四步:運(yùn)行應(yīng)用程序
現(xiàn)在已經(jīng)建立了數(shù)據(jù)庫,我們就可以運(yùn)行應(yīng)用程序了。怎么樣,分享一下自己的勞動(dòng)成果吧!
% java addressbook.PersonPersist
結(jié)束語
我們已經(jīng)討論了如何使用OpenFusion JDO實(shí)現(xiàn)來處理JDO標(biāo)準(zhǔn)。這是一個(gè)全新的領(lǐng)域,開發(fā)人員可以集中精力處理業(yè)務(wù)需求和對(duì)象,而無需對(duì)SQL十分精通。