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文件。