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

在XForum的ant script中,可以看到在compile目標中,在增強之前,把相應的jdo文件拷貝到編譯的目標文件夾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>
進行增強的時候,把classes作為Enhancer源文件夾,JDO Enhancer會自動增強/classes目錄下的所有由對應jdo文件的java classes。
除了為每個persistenceCapable class定義一個.jdo 文件,還可以將一個package中的所有persistencecapable class的meta定義在當前package的一個package.jdo文件中。比如可以將com.redsoft.samples下的所有persistencecapable定義在package.jdo中,這個package.jdo文件應該在/classes/com/redsoft/samples/目錄下。
定義JDO文件:.jdo
JDO文件的用途是告訴Enhancer和JDO哪個java對象是需要由JDO來管理,java對象中的哪些field需要由JDO管理。 由JDO管理的對象是JDO對象,而JDO對象中由JDO進行管理的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對象所在的包( package )。
class 的屬性有:
參數 | 說明 |
---|---|
identity-type | 定義JDO對象的JDO唯一標示ID如何產生和管理。 在Liberator JDO中的可選類型包括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對象的父類也是persistencecapable, 就需要在persistence-capable-superclass中聲明。 假設一個ChildPersistenceAccount,其父類是PersistentAccount |
extension | JDO標準允許JDO廠商對jdo文件進行擴展。目前對class的擴展是允許用戶定義class對應數據庫中表的名字。在sample中,使用擴展來定義了表的名字為Account。如果不使用table擴展,則默認的表名字為class的名字,這里就是PersistentAccount。 |
field | field用來定義JDO對象中哪些field由JDO管理,哪些不由JDO來管理以及如何管理。 |
例子:
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必須是父類的ObjectId class。JDO要求在一個繼承樹中,只能有一個ObjectId class。
filed 的屬性有:
參數 | 說明 |
---|---|
persistence-modifier | 可選值包括: persistent, transactional, none。 persistent表示該field會由JDO實現進行管理,而且這個field將會被保存到數據庫中。 transactional表示該field會由JDO實現進行管理,這個field會參與事務( transaction ),但不會被保存到數據庫中。 none則是該field不由JDO實現管理。 persistence-modifier默認值取決field的類型:
|
primary-key | 可選值包括:true, false。分別代表這個field是否是primary key。默認值為false。 |
null-value | null-value定義了如果field的值為null,JDO實現如何在數據庫中表現該field。 可選值包括:null, default, exception。 null表示數據庫中的值置null。 default表示數據庫中的值置為數據庫默認的置( 比如有些數據庫會int的初值置為0,有些則置為null )。 如果該field不能為null,則可以定義為exception,如果JDO實現在保存該field的時候發現值為null,就拋出exception。 默認值為null。 |
default-fetch-group | 為了優化效率,JDO允許定義JDO對象中fields的加載方式。可以在加載JDO對象的時候一次過全部加載所有的fields,或者在應用程序讀取fields的時候才從數據庫中讀取需要的field。 如果聲明field的default-fetch-group屬性為true,則該field的值會在加載JDO對象的時候從數據中讀取。 default-fetch-group屬性為false,加載JDO對象的時候,改field的值為初始值。當該field的getter被調用的時候,JDO實現才從數據庫中讀取該field的值。 默認值為true。 |
embeded | embeded定義了該field和所屬的class的關系,對應UML中對象之間的從屬關系( Aggregation和Composition )。 embeded只在field的類型為對象( Object )的時候才有效。對primitive type( int, long, double等 ), wrapper( Integer, Long, Double等)和 String,它們的embeded值永遠是true。 對于對象類型的field,embeded為true,表示Composition,該field所指向的對象完全從屬于當前對象( owner object ),應用程序不能獨立地對指向的對象進行查詢或通過JDO Identity直接加載( 該對象沒有JDO Identity ),而是只能通過加載owner object的這個filed來獲得。 embeded為false,表示Aggregation,該field指向的對象是一個獨立的對象,應用程序可以單獨對這個對象進行查詢或通過JDO Identity加載。 默認值為true。 |
collection | 如果JDO對象中的field是collection類型( HashSet, ArrayList ),需要使用collection來聲明。 |
map | 如果JDO對象中的field是map類型( HashMap ),需要使用map來聲明。 |
如果JDO對象中的field不在jdo文件中聲明,則該field所有的屬性都自動取默認值。
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中對象的類型。embedded-element和field中的embeded屬性一樣,聲明了owner object和collection中對象的關系是Aggregation或Composition。默認值和collection中對象的類型相關。規則和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擴展:Extention
Liberator對標準的JDO Meta進行擴展( Extension ),用戶可以客戶化JDO的數據庫設計。
Class Extension
<package name="com.redsoft.samples"> <clas name="Person" identity-type="datastore"> <extension vendor-name="redsoft" key="mode" value="ormapping"/> </class> <package>
extension的參數:
- key - 擴展的名字。有效值為"mode"。
- value - 定義該類是否使用JDO2.0的ormpping特性,有兩種可選值:native和ormapping。
如果不定義該extension,JDO會默認對這個類使用JDO1.01的方式創建數據庫結構和運行時的支持。 這個extension第二個作用是允許在jdo文件中使用orm文件中的定義語法,使用這個擴展可以將jdo和orm兩個配置文件合并為一個jdo文件。