Java資料對象(JDO)的應用
最後更新:2017-02-28
來源:互聯網
上載者:User
對象|資料 在本篇文章中,我們將詳細地討論Sun公司的Java資料對象(JDO)標準。JDO允許我們使用Java對象,支援事務和多使用者。與ODBC不同的是,它使我們無需考慮SQL和與資料庫有關的其他東西。它與序列化也有所區別,因為它支援多個使用者和事務。JDO允許Java開發人員將他們的資料模型用作資料模型,無需在“資料端”、“對象端”之間的轉移方面花費大量的時間。
包括CocoBase、WebGain TOPLink和Castor JDO在內的多種產品都可以實現了JDO標準。既然有一種標準的方法,我們就可以只學習其中的一種,就象有了ODBC,我們就可以使用任何提供了驅動程式的資料庫那樣。
在本篇文章中,我們將使用Prism技術公司的OpenFusion JDO。讀者在後面會發現,只有很小一部分代碼使用了PrismTech API,其他部分都使用了標準的JDO標準。
建立Person對象
我們將首先建立一個Person對象,該對象遵循了JavaBean的慣例,可以對其屬性執行get和set操作。需要注意的是,儘管我們是在建立這個類,但它並沒有什麼特別的,它沒有繼承或實現任何基本類。對一個可保持類的要求是:
1、所有域必須能夠被JDO類訪問(public或set*方法)
2、域的資料類型必須符合JDO規格。
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;
// 允許我們使用構造器建立Person對象
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;
}
}
建立PersonPersist對象管理保留性
現在已經有了Person對象,我們需要建立一些代碼來管理這種保留性。下面我們將詳細討論這些代碼,並學習如何:
1、初始化JDO保留性管理器。
2、向資料庫中輸入三個人的資料。
3、從資料庫中顯示人的資料。
4、修改其中一個人的名字。
5、從資料庫中刪除一個人的資料。
6、在main()方法中進行相關的處理。
第一步:初始化JDO保留性管理器
我們從OpenFusion實現中匯入了標準的JDO類和ManagedConnectionFactory,當然了我們也可以將它們抽象成一個獨立的類。構造器使用javax.jdo.PersistenceManagerFactoryClass屬性設定串連代理,這一點與在JDBC中設定資料庫驅動程式的屬性很相似。
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;
// 需要保持的人的數組
private Person[] people;
// 現有物件識別碼的向量
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()的靜態方法中建立的,該代理需要JDBC URL、JDBC驅動程式、使用者名稱和口令。
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;
}
第二步:在資料庫中輸入三個人的資料
PersistPeople()使用Person.java檔案中的構造器建立了3個人的資料。。我們要作的第一件事是通過
getPersistenceManager()獲得一個保留性管理器,然後建立一個執行我們的任務的事務。為了保持這一對象結構圖,我們簡單地調用makePersistentAll( Object[] )方法即可。代碼底部的for()迴圈獲得每個保持對象的唯一的ID,並儲存起來供以後使用。
public void persistPeople() {
// 建立人的資料的數組
people = new Person[SIZE];
// 建立3個人的資料
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個人的資料
pm = pmf.getPersistenceManager();
transaction = pm.currentTransaction();
pm.makePersistentAll(people);
transaction.commit();
// 擷取被保持對象的對象ID
for(int i = 0; i < people.length; i++) {
id.add(pm.getObjectId(people[i]));
}
// 關閉現有的保持性管理器,保證對象是從資料庫而不是從保持性管理器的緩衝中讀取的
pm.close();
}
下面是一些可以針對保持性管理器的其他方法:
使執行個體成為可保持的:獲得一個臨時對象,並保持它。
刪除可保持執行個體:從資料存放區庫中刪除資訊。
使執行個體臨時化:使執行個體與保留性管理器分離,而不刪除在資料存放區庫中的資訊。
使執行個體處於保持狀態 刪除保持的執行個體 使執行個體處於臨時狀態
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)
(這裡是一個4X3的表格,可以參閱原稿中的英文表格)
第三步:顯示資料庫中人的資訊
顯示資訊代碼以獲得保留性管理器開始。我們使用上面代碼中用persistPeople()方法儲存的對象ID獲得對象,調用對象的方法━━在本例中是gets,來得到我們輸入的資訊。我們可以發現,要保持我們的對象,並不需要編寫大量的代碼。
public void display(int end) {
Person person;
int max = end <= SIZE ? end : SIZE;
// 獲得一個新的保留性管理器
pm = pmf.getPersistenceManager();
// 從資料庫中擷取對象並進行顯示
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();
}
第四步:改變其中一個人的名字
改變儲存在資料庫中的一個人的資訊的代碼也十分簡單,它與顯示資料庫中人的資訊的代碼非常類似。在這裡,我們需要建立一個事務(因為要修改其中的記錄),使用定義的setName()方法修改一個人的名字,最終提交該事務,儲存所作的修改。這種操作與處理臨時對象之間真正的差別是,我們考慮是事務。
public void change() {
Person person;
// 從資料存放區庫中擷取對象
pm = pmf.getPersistenceManager();
transaction = pm.currentTransaction();
// 修改第二個保持記錄的DataString欄位
person = (Person) pm.getObjectById(id.elementAt(1),
false);
person.setName("Steve Gerrard");
// 提交事務並關閉保留性管理器
transaction.commit();
pm.close();
}
第五步:刪除一個人的資料
你自己能夠想象出從資料庫中刪除第二設定檔的代碼嗎?因為我們已經瞭解了所有編寫這一代碼所需要的知識。仔細地研究一下下面的代碼就會發現,我們使用了第二步中的保留性管理器方法中提到的deletePersistent()方法。
public void delete() {
// 從資料庫中擷取對象
pm = pmf.getPersistenceManager();
transaction = pm.currentTransaction();
// 從資料庫中刪除第二個人的資訊,並從ID向量中刪除其ID
pm.deletePersistent(pm.getObjectById(id.remove(1),
false));
// 提交事務並關閉保留性管理器
transaction.commit();
pm.close();
}
第六步:在main()方法中運行上面的代碼
最後,整個代碼需要有一個main()串起來,在資料庫中輸入人的資訊、改變其中一個人的名字,然後刪除該人的資料。如果運行這一程式,就會看到程式運行到每一步時的地址簿。
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:建立JDOEnhancer的JDO描述符
現在,我們已經編寫好了整個應用程式的原始碼,下一步需要作的就是建立一個JDOEnhancer將要使用的
JDO描述符。讀者一定會問,JDOEnhancer是什嗎?JDO架構是基於下面的理念的:一個JDO實現能夠擷取類的位元組碼,對它們進行處理,添加一些必要的功能。例如,JDOEnhancer將使類實現PersistanceCapable介面(因此我們不用自己編程實現這一介面),而且能夠實現該介面中的一些方法。因此在對代碼編譯後我們就會發現,我們必須運行JDOEnhancer對位元組碼進行適當的處理。我們需要建立一個給出我們需要保持的類的資訊的描述符檔案,這一檔案如下所示:
<?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>
這隻是一個最基本的檔案,但能夠滿足我們的要求。當然了,還有許多更複雜的映射。下面是OpenFusion例子中一個稍微複雜一些的映射:
<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>
現在我們已經編寫好了代碼和JDO描述符檔案,我們將對它們進行整合,並討論如何建立整個系統。要建立整個系統,我們只需要簡單的幾步工作即可:
1、編譯代碼。
2、運行JDOEnhancer。
3、使用JDOEnhancer的輸出建立資料庫。
4、運行應用程式。
第一步:編譯代碼
我想廣大的讀者想必已經知道如何運行javac了吧。在運行javac之前,我們只要保證正確地設定CLASSPATH就可以了。下面是一個在Windows平台上運行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
第二步:運行JDOEnhancer
JDOEnhancer需要使用在上一步編譯中得到的位元組碼和我們先前建立的JDO描述符檔案。下面是OpenFusion JDOEnhancer的完整文法:
java com.prismt.j2ee.jdo.enhancer.JDOEnhancer
命令選項:
-cp 開始搜尋需要強化的類的基本路徑,與CLASSPATH不同,它是編譯後的可保持類所在的目錄
-oc 儲存強化後的類的目錄
-pd JDO描述符檔案
可選項:
-db 指定目標資料庫 [oracle、sybase等]
-od 產生SQL指令碼的目錄
下面是為建立我們的應用程式而運行JDOEnhancer的一個例子:
% java com.prismt.j2ee.jdo.enhancer.JDOEnhancer -oc . -pd
person.jdo -db oracle -od db -cp .
第三步:使用JDOEnhancer的輸出建立資料庫
,只要使用?db和-od可選項,JDOEnhancer就能夠建立建立資料庫的資料庫指令碼。它能夠建立許多指令碼,但其中有一個的名字叫load_all.sql,開啟該檔案並將它載入到一個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
;
第四步:運行應用程式
現在已經建立了資料庫,我們就可以運行應用程式了。怎麼樣,分享一下自己的勞動成果吧!
% java addressbook.PersonPersist
結束語
我們已經討論了如何使用OpenFusion JDO實現來處理JDO標準。這是一個全新的領域,開發人員可以集中精力處理業務需求和對象,而無需對SQL十分精通。