JDO對(duì)象的 jdo 文件( 如Account.jdo )就是它的JDO Metadata。 JDO Enhancer在增強(qiáng)java對(duì)象的時(shí)候需要根據(jù)jdo文件來(lái)進(jìn)行。 另外在應(yīng)用程序運(yùn)行的時(shí)候( runtime ),也需要讀取jdo文件。
JDO文件的位置
JDO文件在增強(qiáng)時(shí)和運(yùn)行的時(shí)候,都需要和相對(duì)應(yīng)的class文件處在同一位置上。
以開(kāi)源論壇XForum中的PersistentAccount為例。PersistentAccount所在的package為: org.redsoft.forum.dao,則Account.jdo再進(jìn)行增強(qiáng)和運(yùn)行的時(shí)候,也也必須和Account.class都處在 classes/org/redsoft/forum/dao的位置上。

在XForum的ant script中,可以看到在compile目標(biāo)中,在增強(qiáng)之前,把相應(yīng)的jdo文件拷貝到編譯的目標(biāo)文件夾classes中。
<target name="compile" depends="init"> <javac srcdir="${src}" destdir="${build}" debug="on"> <classpath refid="forum.classpath"/> </javac> <!-- copy jdo files --> <copy todir="${build}" > <fileset dir="src/java" > <include name="**/*.jdo"/> </fileset> </copy> <copy todir="${build}" > <fileset dir="src/java" > <include name="**/*.properties"/> </fileset> </copy> </target>
進(jìn)行增強(qiáng)的時(shí)候,把classes作為Enhancer源文件夾,JDO Enhancer會(huì)自動(dòng)增強(qiáng)/classes目錄下的所有由對(duì)應(yīng)jdo文件的java classes。
除了為每個(gè)persistenceCapable class定義一個(gè).jdo 文件,還可以將一個(gè)package中的所有persistencecapable class的meta定義在當(dāng)前package的一個(gè)package.jdo文件中。比如可以將com.redsoft.samples下的所有persistencecapable定義在package.jdo中,這個(gè)package.jdo文件應(yīng)該在/classes/com/redsoft/samples/目錄下。
定義JDO文件:.jdo
JDO文件的用途是告訴Enhancer和JDO哪個(gè)java對(duì)象是需要由JDO來(lái)管理,java對(duì)象中的哪些field需要由JDO管理。 由JDO管理的對(duì)象是JDO對(duì)象,而JDO對(duì)象中由JDO進(jìn)行管理的Fields是Managed Fields。
JDO文件以xml的方式定義。根Element( root element )為
<?xml version="1.0"?> <!DOCTYPE jdo SYSTEM "file:/javax/jdo/jdo.dtd"> <jdo> <package name="org.redsoft.forum.dao"> <class name="PersistentAccount" identity-type="application" objectid-class="Account_PK"> <extension vendor-name="Liberator" key="table" value="account"/> <field name="userName" persistence-modifier="persistent" primary-key="true" null-value="none" default-fetch-group="true" embedded="true"> </field> <field name="password" persistence-modifier="persistent" primary-key="false" null-value="none" default-fetch-group="true" embedded="true"> </field> <field name="email" persistence-modifier="persistent" primary-key="false" null-value="none" default-fetch-group="true" embedded="true"> </field> <field name="columnWriter" persistence-modifier="persistent" primary-key="false" null-value="none" default-fetch-group="true" embedded="true"> </field> </class> </package> </jdo>
package :
聲明java對(duì)象所在的包( package )。
class 的屬性有:
參數(shù) | 說(shuō)明 |
---|---|
identity-type | 定義JDO對(duì)象的JDO唯一標(biāo)示ID如何產(chǎn)生和管理。 在Liberator JDO中的可選類(lèi)型包括datastore和application。 如果identity-type選用datastore,則忽略objectid-class。 如果選用application,則必須定義objectid-class。 在上面的sample中,com.redsoft.forum.dao.Account_PK是PersistenceAccount的JDO objectid class。 |
persistence-capable-superclass | 如果JDO對(duì)象的父類(lèi)也是persistencecapable, 就需要在persistence-capable-superclass中聲明。 假設(shè)一個(gè)ChildPersistenceAccount,其父類(lèi)是PersistentAccount |
extension | JDO標(biāo)準(zhǔn)允許JDO廠商對(duì)jdo文件進(jìn)行擴(kuò)展。目前對(duì)class的擴(kuò)展是允許用戶(hù)定義class對(duì)應(yīng)數(shù)據(jù)庫(kù)中表的名字。在sample中,使用擴(kuò)展來(lái)定義了表的名字為Account。如果不使用table擴(kuò)展,則默認(rèn)的表名字為class的名字,這里就是PersistentAccount。 |
field | field用來(lái)定義JDO對(duì)象中哪些field由JDO管理,哪些不由JDO來(lái)管理以及如何管理。 |
例子:
package org.redsoft.forum.dao; public class ChildPersistentAccount extends PersistentAccount{ private int age; public ChildPersistentAccount(){ } public ChildPersistentAccount( final String userName, final String password, final String email, final int age) { super(userName, password, email); this.age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
它的JDO文件:
<?xml version="1.0"?> <!DOCTYPE jdo SYSTEM "file:/javax/jdo/jdo.dtd"> <jdo> <package name="org.redsoft.forum.dao"> <class name="ChildPersistentAccount" identity-type="application" persistence-capable-superclass="PersistentAccount" objectid-class="Account_PK"> <extension vendor-name="Liberator" key="table" value="account"/> <field name="age" persistence-modifier="persistent" primary-key="true" null-value="none" default-fetch-group="true" embedded="true"> </field> </class> </package> </jdo>
在ChildPersistentAccount的JDO文件中,ObjectId class必須是父類(lèi)的ObjectId class。JDO要求在一個(gè)繼承樹(shù)中,只能有一個(gè)ObjectId class。
filed 的屬性有:
參數(shù) | 說(shuō)明 |
---|---|
persistence-modifier | 可選值包括: persistent, transactional, none。 persistent表示該field會(huì)由JDO實(shí)現(xiàn)進(jìn)行管理,而且這個(gè)field將會(huì)被保存到數(shù)據(jù)庫(kù)中。 transactional表示該field會(huì)由JDO實(shí)現(xiàn)進(jìn)行管理,這個(gè)field會(huì)參與事務(wù)( transaction ),但不會(huì)被保存到數(shù)據(jù)庫(kù)中。 none則是該field不由JDO實(shí)現(xiàn)管理。 persistence-modifier默認(rèn)值取決field的類(lèi)型:
|
primary-key | 可選值包括:true, false。分別代表這個(gè)field是否是primary key。默認(rèn)值為false。 |
null-value | null-value定義了如果field的值為null,JDO實(shí)現(xiàn)如何在數(shù)據(jù)庫(kù)中表現(xiàn)該field。 可選值包括:null, default, exception。 null表示數(shù)據(jù)庫(kù)中的值置null。 default表示數(shù)據(jù)庫(kù)中的值置為數(shù)據(jù)庫(kù)默認(rèn)的置( 比如有些數(shù)據(jù)庫(kù)會(huì)int的初值置為0,有些則置為null )。 如果該field不能為null,則可以定義為exception,如果JDO實(shí)現(xiàn)在保存該field的時(shí)候發(fā)現(xiàn)值為null,就拋出exception。 默認(rèn)值為null。 |
default-fetch-group | 為了優(yōu)化效率,JDO允許定義JDO對(duì)象中fields的加載方式??梢栽诩虞dJDO對(duì)象的時(shí)候一次過(guò)全部加載所有的fields,或者在應(yīng)用程序讀取fields的時(shí)候才從數(shù)據(jù)庫(kù)中讀取需要的field。 如果聲明field的default-fetch-group屬性為true,則該field的值會(huì)在加載JDO對(duì)象的時(shí)候從數(shù)據(jù)中讀取。 default-fetch-group屬性為false,加載JDO對(duì)象的時(shí)候,改field的值為初始值。當(dāng)該field的getter被調(diào)用的時(shí)候,JDO實(shí)現(xiàn)才從數(shù)據(jù)庫(kù)中讀取該field的值。 默認(rèn)值為true。 |
embeded | embeded定義了該field和所屬的class的關(guān)系,對(duì)應(yīng)UML中對(duì)象之間的從屬關(guān)系( Aggregation和Composition )。 embeded只在field的類(lèi)型為對(duì)象( Object )的時(shí)候才有效。對(duì)primitive type( int, long, double等 ), wrapper( Integer, Long, Double等)和 String,它們的embeded值永遠(yuǎn)是true。 對(duì)于對(duì)象類(lèi)型的field,embeded為true,表示Composition,該field所指向的對(duì)象完全從屬于當(dāng)前對(duì)象( owner object ),應(yīng)用程序不能獨(dú)立地對(duì)指向的對(duì)象進(jìn)行查詢(xún)或通過(guò)JDO Identity直接加載( 該對(duì)象沒(méi)有JDO Identity ),而是只能通過(guò)加載owner object的這個(gè)filed來(lái)獲得。 embeded為false,表示Aggregation,該field指向的對(duì)象是一個(gè)獨(dú)立的對(duì)象,應(yīng)用程序可以單獨(dú)對(duì)這個(gè)對(duì)象進(jìn)行查詢(xún)或通過(guò)JDO Identity加載。 默認(rèn)值為true。 |
collection | 如果JDO對(duì)象中的field是collection類(lèi)型( HashSet, ArrayList ),需要使用collection來(lái)聲明。 |
map | 如果JDO對(duì)象中的field是map類(lèi)型( HashMap ),需要使用map來(lái)聲明。 |
如果JDO對(duì)象中的field不在jdo文件中聲明,則該field所有的屬性都自動(dòng)取默認(rèn)值。
collection 例子:
<field name="orderDates" persistence-modifier="persistent" primary-key="false" null-value="none" default-fetch-group="true" embedded="true"> <collection element-type="java.util.Date" embedded-element="true"/> </field>
element-type聲明了collection中對(duì)象的類(lèi)型。embedded-element和field中的embeded屬性一樣,聲明了owner object和collection中對(duì)象的關(guān)系是Aggregation或Composition。默認(rèn)值和collection中對(duì)象的類(lèi)型相關(guān)。規(guī)則和field的embeded一致。
map 例子:
<field name="myProjects" persistence-modifier="persistent" primary-key="false" null-value="none" default-fetch-group="false"> <map key-type="java.lang.String" value-type="com.redsoft.samples.Project"/> </field>
Liberator擴(kuò)展:Extention
Liberator對(duì)標(biāo)準(zhǔn)的JDO Meta進(jìn)行擴(kuò)展( Extension ),用戶(hù)可以客戶(hù)化JDO的數(shù)據(jù)庫(kù)設(shè)計(jì)。
Class Extension
<package name="com.redsoft.samples"> <clas name="Person" identity-type="datastore"> <extension vendor-name="redsoft" key="mode" value="ormapping"/> </class> <package>
extension的參數(shù):
- key - 擴(kuò)展的名字。有效值為"mode"。
- value - 定義該類(lèi)是否使用JDO2.0的ormpping特性,有兩種可選值:native和ormapping。
如果不定義該extension,JDO會(huì)默認(rèn)對(duì)這個(gè)類(lèi)使用JDO1.01的方式創(chuàng)建數(shù)據(jù)庫(kù)結(jié)構(gòu)和運(yùn)行時(shí)的支持。 這個(gè)extension第二個(gè)作用是允許在jdo文件中使用orm文件中的定義語(yǔ)法,使用這個(gè)擴(kuò)展可以將jdo和orm兩個(gè)配置文件合并為一個(gè)jdo文件。