索引
1. JDO映射概述
我们在本前文中对Castor XML映射进行了详细的描述,并对Castor JDO做了一个概括介绍。Castor JDO在为XML文档与Java对象之间建立映射的同时,也提供了Java对象与关系数据库之间的映射机制,通常称为O/R映射。Castor映射文件可以同时为XML文档与Java对象,数据库关系表与Java对象之间提供映射信息。本文将对Castor O/R映射定义给出详细的描述。
下面是Castor O/R映射定义的例子:
<mapping xmlns="">
<description>Castor generated mapping filedescription>
<class name="ZB_JG_SJB" identity="NUM_ID">
<description>Default mapping for class ZB_JG_SJBdescription>
<map-to table="ZB_JG_SJB"/>
<field name="NUM_ID" type="int" required="true">
<sql name="NUM_ID" type="decimal" dirty="check"/>
field>
<field name="time" type="java.util.Date" required="true">
<sql name="time" type="timestamp" dirty="check"/>
field>
<field name="unirow" type="java.lang.String" required="true">
<sql name="unirow" type="varchar" dirty="check"/>
field>
<field name="status" type="java.lang.String" required="true">
<sql name="status" type="varchar" dirty="check"/>
field>
<field name="insert_Date" type="java.util.Date" required="true">
<sql name="insert_Date" type="timestamp" dirty="check"/>
field>
class> mapping> | |
与Castor XML映射定义类似,一个Java类(节点)通过节点的“table”属性映射为一张数据库表(上例为<map-to table="ZB_JG_SJB"/>)。Java类字段(节点)映射为数据库表中的列(通过节点表示)。
本文将不给出Mapping映射文件中各节点的Schema定义,关于其定义参考前文或Castor映射定义Schema文档。
2. 映射定义详解
2.1Mapping文件的根节点
如上例Mapping文件所示,Mapping文件的根节点为<mapping>。<mapping>节点下的节点包括:
ü 一个<description>节点,可选的,用于添加描述信息
ü 一个或多个<include>节点,用于引用其他的映射文件
ü 一个或多个<class>节点,用于描述每一个定义Mapping的Java类
ü 一个或多个<key-generator>节点,该节点在Castor JDO中用于自动生成记录的主键。我们将在下文中对其做详细解释。
2.2节点定义
<class>节点包含了Java类与数据库关系表之间映射的所有信息。该节点及其子节点详细描述了Java类中各个字段属性与数据库表列信息的映射关系。
2.2.1 节点的属性
Ø name: 映射的Java类名称,使用类的全名,如”com.acme.MyClass”。
Ø extends: 只有在该类扩展其他类时,使用该参数指定扩展的类。如果被扩展的类未在该Mapping文件中指定,则不能使用该属性。
Ø depends: 在Castor JDO中指明类之间的依赖关系,用于表示数据库表中关联表的概念。关于关联关系参考下一节 关联关系。
Ø auto-complete: 如果该属性值为”true”,则Castor在处理该类时首先采用自省的方式决定该类的字段属性,然后使用Mapping文件中对该字段属性的设定覆盖自省方式的操作。auto-complete属性可以让Castor的默认自省处理方式与Mapping定义方式很好的结合,从而降低对包含很多字段的类进行复杂的设定操作。
Ø identity: 在Castor JDO中使用,用于描述该类实例的主键字段,详细信息参考Castor JDO部分。
Ø access: 在Castor JDO中使用,详细信息参考Castor JDO部分。
Ø key-generator: 在Castor JDO中使用,详细信息参考Castor JDO部分。
2.2.2 节点的子节点
Ø description:可选的属性,用于对该类添加描述性信息
Ø cache-type: 只在Castor JDO中使用,详细信息参考Castor JDO部分。
Ø map-to: 可选属性,如果XML中节点名称与类(Class)名称不同,则使用该节点设定。默认的,Castor会自动分析XML节点名称和类名称之间的映射,如对于Java类”XxxYyy”,Castor会自动映射为XML节点”xxx-yyy”。如果用户不希望Castor自动生成该名称,则可以使用节点来指定XML映射名称。注意:仅用于XML文档中的根节点。
Ø field:节点下包含 零个或多个节点。每个节点用于描述Java类中的一个字段属性。
映射举例
类MyClass映射为数据库TestData表:
package mypackage public class MyClass { public int foo; public String getBar() { ... } public void setBar(String bar) { ... } } | |
TestData表结构如下:
CREATE TABLE TestData ( ‘ID’ int(10) unsigned NOT NULL default '0', ‘Bar’ varchar(45) default NULL, ); | |
用户需要以如下方式设定Mapping映射文件:
2.3节点定义
节点用于指定给定Java类与数据库表名称的映射。
Ø table属性:该Java类所映射的关系数据库表的名称。
2.4< field>节点定义
节点用于描述如何编组/解编Java对象中的字段属性。Castor可以从节点描述中的”name”属性确定Java字段的名称;可以从节点描述中的”type”和”collection”属性确定Java字段的类型;可以从节点描述中的”direct”,”get-method”和”set-method”属性确定Java字段的访问方法。通过上述信息,Castor能够操作Java类中的字段属性。
Castor通过以下两个规则来判定某一字段的类型签名:
u 检查节点中的“类型”属性(”type”和”collection”)
如果节点中没有”collection”属性,”type”属性指定的类型即为该字段的Java类型。”type”属性值既可以是Java对象类型的全限定名(包含包名称),也可以是Castor定义的一系列简称。Castor支持的类型别名及对应的原始Java类型列表如下:
简称 |
原始类型 |
Java类型 |
big-decimal |
N |
java.math.BigDecimal |
big-integer |
Y |
java.math.BigInteger |
boolean |
Y |
java.lang.Boolean.TYPE |
byte |
Y |
java.lang.Byte.TYPE |
bytes |
N |
byte[] |
char |
Y |
java.lang.Character.TYPE |
chars |
N |
char[] |
clob |
N |
java.sql.Clob |
date |
N |
java.util.Date |
double |
Y |
java.lang.Double.TYPE |
float |
Y |
java.lang.Float.TYPE |
int |
Y |
java.lang.Integer.TYPE |
integer |
Y |
java.lang.Integer |
locale |
N |
java.util.Locale |
long |
Y |
java.lang.Long.TYPE |
other |
N |
java.lang.Object |
serializable |
Y |
java.io.Serializable |
short |
Y |
java.lang.Short.TYPE |
sqldate |
Y |
java.sql.Date |
sqltime |
Y |
java.sql.Date |
string |
N |
java.lang.String |
strings |
N |
String[] |
stream |
N |
java.io.InputStream |
timestamp |
N |
java.sql.Timestamp |
Castor会自动将数据库表中的数据转换为上述Java对象类型。如果设定了”collection”属性,collection属性值遵从下面的对象对象列表:
简称 |
原始类型 |
Java类型 |
array |
[] |
[] |
enumerate |
java.util.Enumeration |
- |
collection |
java.util.Collection |
java.util.ArrayList |
set |
java.util.Set |
java.util.HashSet |
arraylist |
java.util.ArrayList |
java.util.ArrayList |
vector |
java.util.Vector |
java.util.Vector |
map |
java.util.Map |
java.util.HashMap |
hashtable |
java.util.Hashtable |
java.util.Hashtable |
sortedset |
java.util.SortedSet |
java.util.TreeSet |
iterator |
java.util.Iterator |
n/a |
Collection集合中的对象为Java类型。对于Hashtable和Map类型的对象,Castor同时存储其键和值。对于其映射,可以使用org.exolab.castor.mapping.MapItem类通过顶层(相对于嵌套类映射)类映射定义和嵌套类映射定义来描述。
u 检查节点中的“签名”属性(”direct”,”set-method”和”get-method”)
如果”direct”属性设定为true,则在Java类定义中,该字段必须具有如下的声明:
public ;
如果”direct”属性设定为false或者该属性被忽略,Castor会通过该属性的存取方法访问该属性。首先,若设定了'get-method' 或 'set-method',Castor会访问如下方法签名:
public ();
或
public void ( value);
若没有设定'get-method' 或'set-method'属性,Castor会尝试访问如下签名方法:
public get();
或
public void set( value);
是指Castor检查<name>属性值,将其首字母转换为大写,其他字符保持不变。
2.4.1 节点的属性
节点可以包含将Java字段映射为XML元素,数据库表列名称等信息。节点可配置的属性如下:
Ø name: 该属性是必须的,即使在该映射类中没有该字段属性。如果配置了”direct”属性,”name”属性值必须是映射对象中的一个public字段(该字段必须是public,非static和非transient的类型)。如果没有”direct”和”get-/set-method”属性设定,“name”属性值对应的字段通过该值确定其访问方法(采用Java Bean规范)。
Ø type: 该字段属性的Java类型。Castor使用该信息将XML信息转换为Java对象信息(如将字符串转换为整型),定义该字段访问方法的签名。如果设定了”collection”属性,该属性信息用于指定集合中对象的类型信息。
Ø required: 在编组和解编过程中,该字段是否可选,默认值为false。
Ø transient: 如果设定为”true”,该字段在处理过程中将被忽略。
Ø direct: 如果为true,该字段在Java类定义中必须是public类型。
Ø collection: 如果该字段存在多个,则Castor使用该属性的设定来处理他们。该类型用于定义对应Java类中集合的类型。
Ø get-method: 可选配置,”name”属性对应Java类字段的访问方法,具体使用参考前文描述。
Ø set-method: 可选配置,”name”属性对应Java类字段的访问方法,具体使用参考前文描述。
Ø create-method: 工厂方法,用于构建FieldHandler实例。
2.4.2 节点的子节点
在O/R Mapping中,节点的子节点包含一个节点,用于描述如何将该字段属性映射的数据库表列信息。
2.5节点定义
节点的用于描述Java字段映射的数据库表列的详细信息。节点的Schema定义如下:
<xsd:element name="sql">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:NMTOKENS" use="optional"/>
<xsd:attribute name="type" type="xsd:string" use="optional"/>
<xsd:attribute name="many-table" type="xsd:NMTOKEN" use="optional"/>
<xsd:attribute name="many-key" type="xsd:NMTOKENS" use="optional"/>
<xsd:attribute name="read-only" type="xsd:boolean" use="optional" default="false"/>
<xsd:attribute name="transient" type="xsd:boolean" use="optional"/>
<xsd:attribute name="dirty" use="optional" default="check">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="check"/>
<xsd:enumeration value="ignore"/>
xsd:restriction>
xsd:simpleType>
xsd:attribute>
xsd:complexType>
xsd:element>
2.5.1 节点的属性
Ø name: 数据库表列名称。
Ø type: 对应数据库列的JDBC类型。Castor支持的JDBC类型及其别名列表如下,在数据处理过程中,Castor会自动在SQL类型和Java类型间进行转换:
SQL Type |
Java Type |
bigint |
java.lang.Long |
binary |
byte[] |
bit |
java.lang.Boolean |
blob |
java.io.InputStream |
char |
java.lang.String |
clob |
java.sql.Clob |
decimal |
java.math.BigDecimal |
double |
java.lang.Double |
float |
java.lang.Double |
integer |
java.lang.Integer |
longvarbinary |
byte[] |
longvarchar |
java.lang.String |
numeric |
java.math.BigDecimal |
real |
java.lang.Float |
smallint |
java.lang.Short |
time |
java.sql.Time |
timestamp |
java.sql.Timestamp |
tinyint |
java.lang.Byte |
varbinary |
byte[] |
varchar |
java.lang.String | |
Ø read-only: 如果值为true,则数据库关系表中的该列将以只读方式操作。不会对其进行更新或删除操作。
Ø transient: 如果该属性值为true,JDO在数据库序列化操作时忽略该字段。如果用户希望在Castor XML编组解编过程中同时忽略该节点,可以通过设定节点的“transient”属性。
Ø dirty:如果该属性值为“ignore”,则JDO在处理该字段的过程中将不检查数据库是否对该字段做了变更。
Ø many-key: 【用于一对多和多对多关系】指定该节点对应的节点所表示的对象所映射的数据库表中外键的列名称。
Ø many-table: 【用于多对多关系】指定多对多关系中的关联中间表的名称。该关联中间表将关联双方联系起来。
说明:关于many-key及many-table属性参考下一节关联关系。
3. 关联关系
3.1关联关系概述
在Castor中,对象之间的关联和依赖被区分为两种不同的关系。对于具有两种不同关系的多个对象,Castor对这些对象的生命周期的维护是不同的。当两个对象为关联关系时,这两个对象必须各自进行创建(create),删除(remove)和更新(update)。
在依赖关系中,一个对象必须在映射定义文件中显式的定义其Java类“depends”另一个Java类。在映射定义文件中未声明依赖(depends)其他类的Java类称为主对象类,在数据库中往往称之为主表。依赖于主类的其他对象类称之为依赖对象类或从表。在Castor映射定义文件中,一个依赖对象类只能依赖于一个主类。
如果一个对象类依赖于其他类,在该类对象在Castor中不能独立的创建,删除和更新。Castor在事务操作过程中,不允许一个依赖对象实例变更其主对象实例。依赖对象和主对象必须都要有主键,要么不使用key-generator,要么都使用key-generator。
下述例子表明,对象类com.xyz.MyDependentObject是一个依赖对象类,com.xyz.MyObject是一个主对象类。MyDependentObject依赖于MyObject。
depends="com.xyz.MyObject"> ...
| |
3.2关联关系的处理
Castor支持一对一,一对多和多对多的关联关系。多对多的关联关系中,由于每一个依赖对象只能有一个主对象,所以对象之间必须是关联(related)的而不是依赖(depends)的。
多对多关联关系中,必须有一个独立的表C用于存储两个关联表A和B之间的关联信息。映射定义文件中节点提供“many-key”和“many-table”两个属性表示这种关系。在多对多关系中,many-table属性必须设定表C;如果表A中的主键名称不同于表C中的外键的名称,则使用many-key属性指定表C中的外键的名称;如果表B中的主键的名称不同于表C中的外键的名称,则使用name属性指定表C中外键的名称。
下面以三个数据库表为例说明多对多关系的映射设定:
employee_table |
id |
name |
salary |
1482 |
Smith, Bob |
$123,456 |
628 |
Lee, John |
$43,210 |
1926 |
Arnold, Pascal |
$24,680 |
department_table |
id |
name |
comment |
3 |
Accounting |
|
7 |
Engineering |
The very important department. :-) |
employee_department |
e_id |
d_id |
… |
… |
上述表中,employee数据对象的映射关系举例如下:
many-table="employee_department" many-key="e_id" name="d_id"/>
| |
4. 延迟加载
支持在一对一,一对多及多对多的关联关系中使用延迟加载。使用延迟加载时,需要设定映射定义文件中的“lazy”属性值为true。
如上所示,在一对一的关联关系中,当Castor加载Department对象时,将不会同时加载其引用的Employee对象。只有使用Dempartment.getEmployee()访问Employee对象实例时,Castor才会将Employee对象数据从数据库加载到内存对象中。如果Employee对象从未被访问过,则Castor将永远不会加载该对象。
在一对多和多对多的关系中,如下所示:
... collection="collection"/>
| |
在集合中的Employee对象只有在应用访问该集合中的对象时(如使用集合的iterator()方法),Castor才会加载该集合内的数据
5. 联合主键
Castor支持联合主键的设定。如果数据库表使用多列唯一标识一条记录,则可以在数据映射定义文件中设定多个主键。如果下面的映射定义文件所示:
多个主键在节点的“identity”属性中以空格分隔。联合主键可以在主对象类,依赖对象类,各种关联关系(一对一,一对多和多对多)及延迟加载中使用。