JDO對象的 jdo 文件( 如Account.jdo )就是它的JDO Metadata。 JDO Enhancer在增強(qiáng)java對象的時(shí)候需要根據(jù)jdo文件來進(jìn)行。 另外在應(yīng)用程序運(yùn)行的時(shí)候( runtime ),也需要讀取jdo文件。
JDO文件的位置
JDO文件在增強(qiáng)時(shí)和運(yùn)行的時(shí)候,都需要和相對應(yīng)的class文件處在同一位置上。
以開源論壇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目錄下的所有由對應(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對象是需要由JDO來管理,java對象中的哪些field需要由JDO管理。 由JDO管理的對象是JDO對象,而JDO對象中由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對象所在的包( package )。
class 的屬性有:
參數(shù) |
說明 |
identity-type |
定義JDO對象的JDO唯一標(biāo)示ID如何產(chǎn)生和管理。
在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中聲明。
假設(shè)一個(gè)ChildPersistenceAccount,其父類是PersistentAccount |
extension |
JDO標(biāo)準(zhǔn)允許JDO廠商對jdo文件進(jìn)行擴(kuò)展。目前對class的擴(kuò)展是允許用戶定義class對應(yīng)數(shù)據(jù)庫中表的名字。在sample中,使用擴(kuò)展來定義了表的名字為Account。如果不使用table擴(kuò)展,則默認(rèn)的表名字為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要求在一個(gè)繼承樹中,只能有一個(gè)ObjectId class。
filed 的屬性有:
參數(shù) |
說明 |
persistence-modifier |
可選值包括: persistent, transactional, none。
persistent表示該field會(huì)由JDO實(shí)現(xiàn)進(jìn)行管理,而且這個(gè)field將會(huì)被保存到數(shù)據(jù)庫中。
transactional表示該field會(huì)由JDO實(shí)現(xiàn)進(jìn)行管理,這個(gè)field會(huì)參與事務(wù)( transaction ),但不會(huì)被保存到數(shù)據(jù)庫中。
none則是該field不由JDO實(shí)現(xiàn)管理。
persistence-modifier默認(rèn)值取決field的類型:
- static field。默認(rèn)值和可選值為none。
- transient field。默認(rèn)值和可選值為none。
- final field。默認(rèn)值和可選值為none。
- persistence-capable 類型的 field。默認(rèn)值為persistent。
- 所有以下類型的field,默認(rèn)值為persistent:
primitives: boolean, byte, short, int, long, char, float, double;
java.lang wrappers: Boolean, Byte, Short, Integer, Long, Character,Float, Double;
java.lang: String, Number;
java.math: BigDecimal, BigInteger;
java.util: Date, Locale, ArrayList, HashMap, HashSet, Hashtable, LinkedList, TreeMap, TreeSet, Vector, Collection, Set, List, and Map;
- 以上類型以外的其它類型的默認(rèn)值都為none。
|
primary-key |
可選值包括:true, false。分別代表這個(gè)field是否是primary key。默認(rèn)值為false。 |
null-value |
null-value定義了如果field的值為null,JDO實(shí)現(xiàn)如何在數(shù)據(jù)庫中表現(xiàn)該field。
可選值包括:null, default, exception。
null表示數(shù)據(jù)庫中的值置null。
default表示數(shù)據(jù)庫中的值置為數(shù)據(jù)庫默認(rèn)的置( 比如有些數(shù)據(jù)庫會(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對象中fields的加載方式。可以在加載JDO對象的時(shí)候一次過全部加載所有的fields,或者在應(yīng)用程序讀取fields的時(shí)候才從數(shù)據(jù)庫中讀取需要的field。
如果聲明field的default-fetch-group屬性為true,則該field的值會(huì)在加載JDO對象的時(shí)候從數(shù)據(jù)中讀取。
default-fetch-group屬性為false,加載JDO對象的時(shí)候,改field的值為初始值。當(dāng)該field的getter被調(diào)用的時(shí)候,JDO實(shí)現(xiàn)才從數(shù)據(jù)庫中讀取該field的值。
默認(rèn)值為true。 |
embeded |
embeded定義了該field和所屬的class的關(guān)系,對應(yīng)UML中對象之間的從屬關(guān)系( Aggregation和Composition )。
embeded只在field的類型為對象( Object )的時(shí)候才有效。對primitive type( int, long, double等 ), wrapper( Integer, Long, Double等)和 String,它們的embeded值永遠(yuǎn)是true。
對于對象類型的field,embeded為true,表示Composition,該field所指向的對象完全從屬于當(dāng)前對象( owner object ),應(yīng)用程序不能獨(dú)立地對指向的對象進(jìn)行查詢或通過JDO Identity直接加載( 該對象沒有JDO Identity ),而是只能通過加載owner object的這個(gè)filed來獲得。
embeded為false,表示Aggregation,該field指向的對象是一個(gè)獨(dú)立的對象,應(yīng)用程序可以單獨(dú)對這個(gè)對象進(jìn)行查詢或通過JDO Identity加載。
默認(rèn)值為true。 |
collection |
如果JDO對象中的field是collection類型( HashSet, ArrayList ),需要使用collection來聲明。 |
map |
如果JDO對象中的field是map類型( HashMap ),需要使用map來聲明。 |
如果JDO對象中的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中對象的類型。embedded-element和field中的embeded屬性一樣,聲明了owner object和collection中對象的關(guān)系是Aggregation或Composition。默認(rèn)值和collection中對象的類型相關(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對標(biāo)準(zhǔn)的JDO Meta進(jìn)行擴(kuò)展( Extension ),用戶可以客戶化JDO的數(shù)據(jù)庫設(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 - 定義該類是否使用JDO2.0的ormpping特性,有兩種可選值:native和ormapping。
如果不定義該extension,JDO會(huì)默認(rèn)對這個(gè)類使用JDO1.01的方式創(chuàng)建數(shù)據(jù)庫結(jié)構(gòu)和運(yùn)行時(shí)的支持。 這個(gè)extension第二個(gè)作用是允許在jdo文件中使用orm文件中的定義語法,使用這個(gè)擴(kuò)展可以將jdo和orm兩個(gè)配置文件合并為一個(gè)jdo文件。