分享
 
 
 

CASTOR JDO 指南

王朝java/jsp·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

CASTOR JDO 指南

现在,越来越多的企业级开发项目中需要一种在众多关系数据库

上进行对象关系映射的技术。遗憾的是,个体组织内部的解决方案很

难构建,而对其进行长期维护和扩展就更难了。虽然有了EJB技术,

但是我发现在某些情况下使用EJB技术往往过于重量级了,这时候适合

的解决方式应该是轻量级的为好。本文中,我将向您介绍了使用 Cast

or JDO 的基础知识, Castor JDO(Java 数据对象 (Java Data Obje

cts))是一种开放源码的、百分之百 Java 关系对象映射框架,Castor

同许多其它技术结合使用,已经将 Java 对象模型绑定到关系数据库、

XML 文档以及 LDAP 目录上。

在本文中,您将了解使用 Castor JDO 的基本知识。我们将从配置

JDO开始;然后是关系数据模型和 Java 对象模型,接下来讨论在

二者之间进行映射的基础知识;最后我们将讨论 Castor JDO 的一

些特性。您将了解一些基本内容,如(关系的和面向对象的)继承、

从属与相关关系、对象查询语言(Object Query Language)实现以

及短事务和长事务的比较。

第一部分:J DO 配置

数据库配置意味着从数据库服务器中获得一个连接,和在java类和数据

表间映射,以及提供数据库服务与客户间的会话。Castor支持目前所有

主流的数据库产品,需要注意的是,它不支持JDBC-ODBC桥接方式。不同

的数据库服务有着不同的配置语法,通过配置数据库服务器对客户提供服

务。

Castor支持的数据库系统列表如下:

1:oracle Oracle 7 and Oracle 8

2:sybase Sybase 11

3:sql-server Microsoft SQL Server

4:db2 DB/2

5:informix Informix

6:postgresql PostgreSQL 7.1

7:hsql Hypersonic SQL

8:instantdb InstantDB

9:interbase Interbase

10:mysql MySQL

11:sapdb SAP DB

下面给出几种数据库系统的配置方式:

Sybase jConnect

<data-source class-name="com.sybase.jdbc2.jdbc.SybDataSource">

<params user="user" password="secret" port-number="4100"

server-name="host" />

</data-source>

Oracle Thin Driver

<database name="ebiz" engine="oracle">

<driver class-name="oracle.jdbc.driver.OracleDriver"

url="jdbc:oracle:thin:@host:post:SID">

<param name="user" value="scott" />

<param name="password" value="tiger" />

</driver>

</database>

InstantDB

<driver class-name="org.enhydra.instantdb.jdbc.idbDriver"

url="jdbc:idb:C:\\castor-0.8.8\\db\\test\\test.prp">

<param name="user" value="" />

<param name="password" value="" />

</driver>

sql-server

<database name="test" engine="sql-server" >

<driver class-name="com.microsoft.jdbc.sqlserver.SQLServerDriver"

url="jdbc:microsoft:sqlserver://localhost:1433">

<param name="user" value="sa" />

<param name="password" value="sa"/>

</driver>

<mapping href="mapping.xml"/>

</database>

第二部分:第一个例子

在这一部分里我将从一个简单的数据模型开始,并让你初步了解如何使用

Castor。

首先我定义一个简单的数据模型,不包含任何的关系。

她的代码如下:

Customer.java

package org.user;

import java.util.*;

public class Customer{

private int _id;

private String _last_name;

private String _first_name;

public int getId()

{

return _id;

}

public void setId( int id )

{

_id = id;

}

public String getFname()

{

return _first_name;

}

public void setFname( String first_name )

{

_first_name = first_name;

}

public String getLname()

{

return _last_name;

}

public void setLname( String last_name )

{

_last_name = last_name;

}

public void toString()

{

return this.getFname()+" "+this.getLname() ","+this.getId();

}

}

正如你所看到的,它可以是一个普通类,当然你也可以实现org.exolab.castor.jdo.

Persistent接口,从而在持久化之前做预处理。

现在让我们来看映射配置文件

mapping.xml

<!DOCTYPE databases PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"

"http://castor.exolab.org/mapping.dtd">

<mapping>

<class name="org.user.Customer" identity="id">

<description>

Customer

</description>

<map-to table="CUSTOMERS"/>

<field name="id" type="integer">

<sql name="ID" type="integer"/>

</field>

<field name="fname" type="string">

<sql name="FIRST_NAME" type="char"/>

</field>

<field name="lname" type="string">

<sql name="LAST_NAME" type="char"/>

</field>

</class>

</mapping>

正如你所看到的,映射文件很简单。<class> 元素支持一些重要的属性和元素。例如,

Customer映射使用 identify 属性来指示对象的哪个特性充当对象标识符。<class>

元素还支持 <map-to> 元素, 该元素告诉 Castor 每个对象映射到什么关系表上。

<field> 元素也支持一些属性。请注意,所有 <field> 和 <sql> 元素的映射都包

含 type 属性。类型属性向 Castor指示:该在内部使用什么 类型转换器来在对象

和关系数据类型之间进行转换。

现在让我们来写一个测试文件:

test.java

import org.user.*;

public class Mytest{

public static final String DatabaseFile = "database.xml";

public static final String MappingFile = "mapping.xml";

public static final String Usage = "Usage: example jdo";

private Mapping _mapping;

private JDO _jdo;

public static void main( String[] args )

{

try

{

Test test = new Ttest();

test.run();

}

catch ( Exception except )

{

except.printStackTrace();

}

}

public Test()

throws Exception

{

// 装载实体关系映射文件

_mapping = new Mapping( getClass().getClassLoader() );

_mapping.loadMapping( getClass().getResource( MappingFile ) );

//装载数据库连接映射文件

_jdo = new JDO();

_jdo.setConfiguration( getClass().getResource( DatabaseFile ).

toString() );

_jdo.setDatabaseName( "test" );

}

public void run()

throws Exception

{

Database db;

Customer customer;

OQLQuery customerOql;

QueryResults results;

db = _jdo.getDatabase();

//注意在持久化对对象包含关系引用时,必须打开这个选项才能够自动持久

化关系对象。

db.setAutoStore(true);

db.begin();

customer = new Customer();

customer.setId(1);

customer.setFname("rain");

customer.setLname("wk");

//持久化数据

db.makePersistent(customer);

//通过装载也可加载数据

// customer = (Customer)db.load(Customer.class,new Integer("1"));

//System.out.println( "select customer: " + customer);

//通过OQL语言查询持久化数据。

customerOql = db.getOQLQuery("SELECT p FROM org.user.Customer p

WHERE p.id =$1");

productOql.bind(1);

results = customerOql.execute();

while ( results.hasMore())

{

customer = (Customer) results.next();

System.out.println( "select customer: " + customer);

}

db.commit();

}

}

结果:

select customer:rain wk ,1

在体验完第一个例子后,想必你对Castor 有了一定的认识,是不是看上去很简单,

Castor帮你是现实过去需要EJB才能实现的实体持久化。这正是我们想要的,一个

轻量级的可以在大多数场合替代EJB的有效技术。我将在接下来的文章中详细讲解

Castor JDO 技术。

第四部分:JDO 关系

上一章我讲解了JDO的持久化,本章将讲解JDO中关于关系的问题。同样的]我将通

过几个例子来详细介绍他的有关特性。

为了处理真实世界的模型,jdo必须能够管理数据模型彼此复杂的关系,在jdo中,

不同种类的关系被归为5种类型:一对多单向,一对多双向,多对一单向,多对一双向,多对多。

在开始之前,我们先定义一个管理接口的适配器,以方便编码。

abstract class PersistentCapable implements Persistent{

private Database _db;

public void jdoPersistent( Database db )

{

_db = db;

}

public void jdoTransient()

{

_db = null;

}

public Class jdoLoad(short accessMode)

{

return null;

}

public void jdoBeforeCreate( Database db )

{

}

public void jdoAfterCreate()

{

}

public void jdoStore(boolean modified)

{

}

public void jdoBeforeRemove()

{

}

public void jdoAfterRemove()

{

}

public void jdoUpdate()

{

}

}

一对多

在一对多的关系下,数据模型中从表有一个指向主表的引用,模型图如下所示

,Oder 和Orderitem 构成了主从表关系,order_id=id 为其关系。一对多关

系是典型的数据库应用。但是从Castor中存储的时候却必须以主(Oder)对象

来持久化,从(Orderitem)做为他的从属对象来对待。

首先让我们来看一下order类。需要注意的是:第一,实现Persistent接口。

第二,建立与OrderItem的引用。

package org.user;

import java.util.*;

public class Order extend PersistentCapable {

private int _id;

private String _name;

private Vector _orderItems = new Vector();

public void setId(int id){

_id = id;

}

public int getId(){

return _id;

}

public void setName(String name){

_name = name;

}

public String getName(){

return _name;

}

public void addOrderItem(OrderItem orderItem){

_orderItems.add(orderItem);

orderItem.setOrder(this);

}

public Vector getOrderItems(){

return _orderItems;

}

}

同样的OrderItem也保持一个Order的引用。

package org.user;

import java.util.*;

public class OrderItem{

private int _id;

private String _name;

private float _price;

private Order _order;

public void setId(int id){

_id = id;

}

public int getId(){

return _id;

}

public void setName(String name){

_name = name;

}

public String getName(){

return _name;

}

public void setPrice(float price){

_price = price;

}

public float getPrice(){

return _price;

}

public void setOrder(Order order){

_order = order;

}

public Order getOrder(){

return _order;

}

}

接下来让我们看一看配置文件的内容。

<class name="org.user.Order" identity="id">

<description>

Order

</description>

<map-to table="ORDERS"/>

<field name="id" type="integer">

<sql name="ID" type="integer"/>

</field>

<field name="name" type="string">

<sql name="NAME" type="char"/>

</field>

<field name="orderItems" type="org.user.OrderItem" required="true"

collection="vector">

<sql many-key="ORDER_ID"/>

</field>

</class>

<class name="org.user.OrderItem" identity="id">

<description>

OrderItem

</description>

<map-to table="ORDERITEM"/>

<field name="id" type="integer">

<sql name="ID" type="integer"/>

</field>

<field name="name" type="string">

<sql name="NAME" type="char"/>

</field>

<field name="price" type="float">

<sql name="PRICE" type="float"/>

</field>

<field name="order" type="org.user.Order">

<sql name="ORDER_ID"/>

</field>

</class>

需要注意的是如下的配置代码:

Order引用了一个外部类型OrderItem,外部字段名称是ORDER_ID ,orderItems属

性返回一个collection结构的对象集合。

<field name="orderItems" type="org.user.OrderItem" required="true"

collection="vector">

<sql many-key="ORDER_ID"/>

同样的OrderItem引用了一个Order类型的关系,字段名称是ORDER_ID。

<field name="order" type="org.user.Order">

<sql name="ORDER_ID"/>

</field>

上面的关系是双向的,他们可以互相观察对方,你可以通过任何一方来导航,但也

可以是单向的,即通过主导航到从,你需要修改部分代码,这里我就不讲了,不过

我建议你使用双向导航。

多对一

在多对一的关系下,数据模型中主表有一个指向从表的引用,模型图如下所示,

Customer 和Address 构成了表关系,多对一关系是典型的数据库应用。是Castor

中存储的时候却必须以主(Customer)对象来持久化,从(Address)做为他的从

属对象来对待。

代码如下.

package org.user;

import java.util.*;

public class Customer extend PersistentCapable {

private int _id;

private String _last_name;

private String _first_name;

private Vector _address =new Vector();

private Address _address;

public int getId()

{

return _id;

}

public void setId( int id )

{

_id = id;

}

public String getFname()

{

return _first_name;

}

public void setFname( String first_name )

{

_first_name = first_name;

}

public String getLname()

{

return _last_name;

}

public void setLname( String last_name )

{

_last_name = last_name;

}

public Address getAddress()

{

return _address;

}

public void addAddress( Address address )

{

_address.add( address );

address.setCustomer(this);

}

public void setAddress(Address address)

{

_address = address;

}

}

package org.user;

public class Address{

private int _id;

private String _street;

private String _city;

private String _state;

private String _zip;

private Customer _customer;

public int getId()

{

return _id;

}

public void setId( int id )

{

_id = id;

}

public String getStreet()

{

return _street;

}

public void setStreet( String street )

{

_street = street;

}

public String getCity()

{

return _city;

}

public void setCity( String city )

{

_city = city;

}

public String getState()

{

return _state;

}

public void setState( String state )

{

_state = state;

}

public String getZip()

{

return _zip;

}

public void setZip( String zip )

{

_zip = zip;

}

public Customer getCustomer()

{

return _customer;

}

public void setCustomer( Customer customer )

{

_customer = customer;

}

}

<class name="org.user.Customer" identity="id">

<description>

Customer

</description>

<map-to table="CUSTOMER"/>

<field name="id" type="integer">

<sql name="ID" type="integer"/>

</field>

<field name="fname" type="string">

<sql name="FIRST_NAME" type="char"/>

</field>

<field name="lname" type="string">

<sql name="LAST_NAME" type="char"/>

</field>

<field name="address" type="org.user.Address">

<sql name="ADDRESS_ID"/>

</field>

</class>

<class name="org.user.Address" identity="id">

<description>

Address

</description>

<map-to table="ADDRESS"/>

<field name="id" type="integer">

<sql name="ID" type="integer"/>

</field>

<field name="street" type="string">

<sql name="STREET" type="char"/>

</field>

<field name="state" type="string">

<sql name="STATE" type="char"/>

</field>

<field name="zip" type="string">

<sql name="ZIP" type="char"/>

</field>

<field name="city" type="string">

<sql name="CITY" type="char"/>

</field>

</class>

Customer引用了一个外部类型Address,字段名称是ADDRESS_ID。

<field name="address" type="org.user.Address">

<sql name="ADDRESS_ID"/>

</field>

多对多

在多对多的关系下,数据模型中表A,表B都有一个指向中间表的引用,模型图如下

所示category 和category_prod构成了表关系,prod和category_prod构成了表关,

这样category和prod构成多对多得关系,这是典型的数据库应用。

代码如下:

package jdo;

import java.util.Vector;

import java.util.Enumeration;

public class Category

{

private int _id;

private Vector _products = new Vector();

private String _name;

public int getId()

{

return _id;

}

public void setId( int id )

{

_id = id;

}

public String getName()

{

return _name;

}

public void setName( String name )

{

_name = name;

}

//public Enumeration getProducts()

public Vector getProducts()

{

return _products;

// return _products.elements();

}

public void addProduct( Product product )

{

if ( ! _products.contains( product ) ) {

System.out.println( "Adding product " + product + "

to category " + this );

_products.addElement( product );

product.addCategories( this );

}

}

public String toString()

{

return "<id: " + _id + " name: " + _name + ">";

}

}

package jdo;

import java.util.Vector;

import java.util.Enumeration;

import org.exolab.castor.jdo.Database;

import org.exolab.castor.jdo.Persistent;

public class Product //implements Persistent

{

private int _id;

private String _name;

private float _price;

private Database _db;

private Vector _categories = new Vector();

public int getId()

{

return _id;

}

public void setId( int id )

{

_id = id;

}

public String getName()

{

return _name;

}

public void setName( String name )

{

_name = name;

}

public float getPrice()

{

return _price;

}

public void setPrice( float price )

{

_price = price;

}

public Vector getCategories()

{

return _categories;

}

public void addCategories( Category category )

{

if ( ! _categories.contains( category ) ) {

_categories.addElement( category );

category.addProduct( this );

}

}

public String toString()

{

return "<id: " + _id + " name: " + _name + ">";

}

}

<!-- Mapping for Product -->

<class name="jdo.Product" identity="id">

<description>Product definition</description>

<map-to table="prod" xml="product" />

<field name="id" type="integer">

<sql name="id" type="integer" />

</field>

<field name="name" type="string">

<sql name="name" type="char" />

</field>

<field name="price" type="float">

<sql name="price" type="numeric" />

</field>

<!-- Product has reference to Category with

many-many relationship -->

<field name="categories" type="jdo.Category" required="true"

collection="vector">

<sql name="category_id"

many-table="category_prod" many-key="prod_id" />

</field>

</class>

<class name="jdo.Category" identity="id">

<description>

A product category, any number of products can belong to

the same category, a product can belong to any number of

categories

</description>

<map-to table="category" xml="category" />

<field name="id" type="integer">

<sql name="id" type="integer"/>

</field>

<field name="name" type="string">

<sql name="name" type="char"/>

</field>

<field name="products" type="jdo.Product" required="true"

collection="vector">

<sql name="prod_id"

many-table="category_prod" many-key="category_id" />

</field>

</class>

Product含有一个 Category引用,附加一个中间表category_prod,字段名称为

category_id;同样 Category也有一个 Product引用,附加一个中间表categor

y_prod,字段名称为prod_id。

<field name="categories" type="jdo.Category" required="true"

collection="vector">

<sql name="category_id"

many-table="category_prod" many-key="prod_id" />

</field>

<field name="products" type="jdo.Product" required="true"

collection="vector">

<sql name="prod_id"

many-table="category_prod" many-key="category_id" />

</field>

在本文中,我们讨论了使用 Castor 将关系数据模型映射到 Java 对象模型的基

础知识。同过这些简单的示例肯定不能涵盖 Castor 的全部能力。实际上,Cast

or 支持许多其它特性,包括键生成、延迟装入、LRU 高速缓存、不同的锁定/访

问方式以及更多。我将在下一部分介绍更多的知识。

参考资料

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有