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的类型:

  • static field。默认值和可选值为none。
  • transient field。默认值和可选值为none。
  • final field。默认值和可选值为none。
  • persistence-capable 类型的 field。默认值为persistent。
  • 所有以下类型的field,默认值为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;
  • 以上类型以外的其它类型的默认值都为none。
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文件。