Castor功能与应用参考四- JDO 概述

索引
1.         Castor JDO 概述
2.         功能特性
3.         简单示例
4.         JDO操作详解
1)        建立数据库连接
i.           JDO用于独立应用
ii.         JDO用于J2EE应用
i.           暂存对象与持久化对象
ii.         执行OQL查询
iii.        创建持久化对象
iv.       删除持久化对象
v.         更新持久化对象
3)        同时使用JDO和XML
5.         JDO数据库配置文件
1)        JDO数据库Schema定义
2)        JDO数据库配置概述
3)        事务声明
i.           本地事务
ii.         全局事务
4)        不同数据库配置示例
1.       Castor JDO 概述
Castor JDO是一个纯Java的对象关系(O/R)映射和数据绑定框架。Castor使用用户定义的映射信息在关系数据库和Java对象之间建立起映射转换关系。从另一个层面说,Castor JDO为Java对象提供了一个数据持久层。
Castor JDO对于Java对象的操作被自动转换为对数据库的查询,更新,插入和删除操作。在事务边界中,对于Java对象的修改,在执行提交(commit)操作时自动提交给数据源。因此, Java开发人员在构建了数据库表和映射信息后,视角的重心从数据库操作层面转移到Java对象的操作上。Castor JDO将数据的序列化和业务逻辑分离为更好的进行面向对象的设计提供了支持,这在大型项目中特别重要。
Castor JDO采用类似于Castor XML样式的Mapping映射文件。下文我们将详述Castor JDO的概念与应用。
2.       功能特性
Ø Castor JDO是一个事务框架。当数据对象被Castor加载后,Castor会对该数据对象进行锁定并对其他事务隔离。Castor通过 xa.Synchronzation支持完整的两阶段事务提交。Castor提供数据对象的“shared”、“exclusive”、“database locked”和“read-only”等多种数据读写策略。
n 共享读(shared),Castor默认的数据锁定策略,在多个事务查询同一数据对象,更新操作作用于各自的对象拷贝时适用。
n 排斥读(exclusive),Castor提供一个内存锁,多个事务在同一数据对象上执行更新操作时,以竞争的方式获取内存锁来完成对象的更新操作。
n 数据库锁(dabase locked),此策略应用于多个应用程序同时访问数据库数据的场景,如果其他应用程序使用Castor以外的其他方式访问数据库,则考虑使用该策略。
n 只读(read-only),不对数据做任何锁定。使用该策略的所有数据对象都不加锁,这些对象也不参与事务提交和回滚。
Ø 支持“长时间事务(long transactions)”,通过内置的数据“脏检查(dirty-checking)”防止用户在初始事务中对数据变更后被重复修改,从而允许用户在一个事务内读取对象,修改更新,然后在第二个事务中提交。通过自动的数据“脏检查(dirty-checking)”和死锁侦测,Castor可以确保数据的一致性并减少不必要的数据库更新操作。
Ø 支持OMG(Object Management Group)3.0对象查询语言规范OQL的一个子集用来与数据库进行交互。OQL与SQL类似,但其操作作用于Java对象而不是数据库表。
Ø 实现了一个数据缓存池来减少数据库的频繁访问,同时提供了几种可选的LRU类型的缓存策略。
Ø 支持一对一,一对多,多对多等多种数据库关系,支持对象和数据库记录的继承。Castor区分对象数据生命周期中的关联(如联合)和依赖(如聚合)关系,在各自对象的生命周期中,自动创建和删除依赖的对象数据。
Ø 支持数据库表多主键,并提供多种主键生成器。
Ø 自动处理包含Java集合类型的对象的存储,包括Vector,Hashtable,Collection,Set和Map。通过“延迟加载”减少不必要的数据库访问。延迟加载可以在每一个集合类型的字段上设定。
Ø 支持Java对象类型与数据库类型间的自动转换。
Ø Castor JDO在同一个应用中使用多个类加载器,使得其可以在EJB容器或Servlet容器中使用。
Ø Castor XML框架和Castor JDO可以无缝集成使用,同时处理O/R映射和Java对象-XML 数据绑定。
Ø Castor JDO支持以下数据库系统:
n DB2
n Derby
n Generic DBMS
n Hypersonic SQL
n Informix
n InstantDB
n Interbase
n MySQL
n Oracle              (8.1.x,9.x,10g)
n PostgreSQL
n Progress
n SAP DB / MaxDB
n SQLServer
n Sybase
用户可以针对特定数据库提供自己的JDBC驱动接口实现插入到Castor中,前提是该数据库支持JDBC2.0,多结果集(ResultSet)和事务。
3.       简单的示例
下面我们以一个简单的示例来展示Castor JDO使用过程中的一些关键要素。类似于Castor XML,Castor JDO中用户需要提供数据实体的Java类定义,Java类模型与数据库表结构的映射信息。此外,在多数情况下用户还要提供数据库配置文件。在Castor XML中,用户使用Marshaller和Unmarshaller编组和解编对象/XML数据,在Castor JDO中,用户使用JDOManager持久化和读取Java对象/关系数据。
首先,我们定义两个Java类:产品分类Catalogue和产品Product。每一产品分类可以存在多种产品。

public class Catalogue {
   private long id;
   private List products = new ArrayList();
   
   public long getId() { ... }
   public void setId(long id) { ... }
   public String getProducts() { ... }
   public void setProducts(List products) { ... }
}
public class Product {
   private long id;
   private String description;
   public long getId() { ... }
   public void setId(long id) { ... }
   public String getDescription() { ... }
   public void setDescription(String description) { ... }
}

为了实现上述Java对象的持久化操作,如查询产品,从一种产品分类中删除产品等,我们需要定义Java类与数据库表及列之间的映射关系。Castor JDO Mapping文件与Castor XMLMapping文件具有相同的结构,如下所示:

<class name="org.castor.sample.Catalogue">
   <map-to table="catalogue"/>
   <field name="id" type="long">
      <sql name="id" type="integer" />
   </field>
   <field name="products" type="org.castor.sample.Product" collection="arraylist">
      <sql many-key="c_id" />
   </field>
</class>
<class name="org.castor.sample.Product">
   <map-to table="product"/>
   <field name="id" type="long">
      <sql name="id" type="integer" />
   </field>
   <field name="description" type="string">
      <sql name="desc" type="varchar" />
   </field>
</class>

定义了Castor JDO Mapping 文件后,我们即可以使用Castor JDOManager 实现Java 对象与数据库表记录之间的互操作。在此之前我们先看一下Castor JDO Configuraton 文件,在此文件中定义了数据库连接配置信息。Castor JDO 配置文件不是必须的,Castor JDO 提供了使用API 直接设定数据连接参数。

<?xml version="1.0" ?>
<!DOCTYPE jdo-conf PUBLIC "-//EXOLAB/Castor JDO Configuration DTD Version 1.0//EN" "http://castor.org/jdo-conf.dtd">
<jdo-conf>
 <database name="hsqldb" engine="hsql">
    <driver class-name="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:hsql://localhost:9002/dbname">
      <param name="user" value="sa"/>
      <param name="password" value=""/>
    </driver>
    <mapping href="mapping.xml"/>
 </database>
 <transaction-demarcation mode="local"/>
</jdo-conf>

在下述代码中,Castor JDO 读取数据库配置信息并构造一个名为“sample ”的JDOManager 实例;然后通过getDatabase() 方法获取与数据库的连接,从数据库中获取一个产品分类的ID (主键)值为“1 ”的记录并加载成一个产品分类对象,最后提交并关闭与数据库的连接。

JDOManager.loadConfiguration("jdo-conf.xml");
JDOManager jdoManager = JDOmanager.createInstance("sample");
Database database = jdoManager.getDatabase();                        
database.begin();
Catalogue catalogue = database.load(catalogue.class, new Long(1));
database.commit();
database.close();

4.       JDO操作详述
4.1连接数据库
Castor JDO支持独立应用和J2EE应用两种运行环境。独立应用需要配置数据库连接并显式管理事务,J2EE应用使用JNDI获取一个预先配置的数据库连接并使用 UserTransaction或容器控制的事务(CMT)来处理事务。
 
4.1.1          JDO用于独立应用
在独立的Java应用中,用户需要自己定义JDO数据配置信息,控制事务及其调用。JDO数据库配置信息使用一个独立的XML配置文件定义,并在其中指明映射文件。用户也可以使用 org.exolab.castor.jdo.util.JDOConfFactory类在程序代码中设定数据库配置。关于JDO数据库的详细配置请参考后续文档。
org.exolab.castor.jdo.JDOManager设定要构造数据库实例名称及其属性,用来与数据库建立连接。JDOManager的构造过程分为两步:
Ø 使用JDOManager的静态方法 loadConfiguration()加载数据库配置信息。
Ø 使用静态方法 createInstance(java.lang.String)方法构造一个JDOManager实例,createInstance()方法接收一个String类型的参数,用于指明第一步加载的数据库配置信息中定义的数据库名称。
Castor JDO使用org.exolab.castor.jdo.Database对象表示与数据库的一个连接。Database实例是非线程安全的,用户不应该在并发线程中使用。同时构造多个Database对象实例的开销很小,Castor JDO在每一个开放的事务中获取一个连接。
下面的代码为名称为“mydb”数据库构造一个JDOManager实例, 打开一个数据库连接,开始一个事务,然后关闭数据库连接。实际使用中,用户应该进行必要的异常处理。

JDOManager jdoManager;
Database db;
//加载一个JDO数据库配置文件,并为名称为'mydb'的数据库构造一个JDOManager实例
JDOManager.loadConfiguration("jdo-conf.xml");
jdoManager = JDOManager.createInstance("mydb");
// 获取一个数据库连接
Database db = jdoManager.getDatabase(); 
// 开始一个事务
db.begin();
// 处理某些操作
. . .
// 提交事务并关闭数据库连接
db.commit();
db.close();    

 
4.1.2          JDO用于J2EE Application
J2EE 应用程序依赖于J2EE 容器来配置数据库连接并使用JNDI 查找配置。Castor JDO 在J2EE 应用系统中不希望直接构造JDOManager 实例用JNDI 对其进行查找,而是推荐用户将JDOManager 实例添加到java:comp/enb/jdo 名称空间下,以遵循查找JDBC 资源的惯例。下述代码展示了用JNDI 查找一个Database 实例并使用JTA UserTransaction 接口来控制处理事务:
 

InitialContext ctx;
UserTransaction ut;
Database        db;
// Lookup databse in JNDI
ctx = new InitialContext();
db = (Database) ctx.lookup( "java:comp/env/jdo/mydb" );
// Begin a transaction
ut = (UserTransaction) ctx.lookup( "java:comp/UserTransaction" );
ut.begin();
// Do something
. . .
// Commit the transaction, close database
ut.commit();
db.close();

对于EJB实体Bean,如果事务是由容器控制控制处理,则没有必要显式的调用begin/commit方法,这一切都由应用服务器来控制开始一个事务,并在合适的时候执行commit/rollback方法。下面的代码展示了容器控制下的事务:

InitialContext ctx;
UserTransaction ut;
Database        db;
// Lookup databse in JNDI
ctx = new InitialContext();
db = (Database) ctx.lookup( "java:comp/env/jdo/mydb" );
// Do something
. . .
// Close the database
db.close();

4.2使用JDO Database执行持久化操作
 
4.2.1          暂存对象与对持久化象
所有的JDO 操作都在一个事务上下文之内。JDO 将数据从数据库加载到内存对象,允许对对象进行修改,然后在事务提交时将对象的新状态持久化到数据库。所有的对象可以分为两种状态:暂存(transient) 和持久化(persistent) 。
Ø 暂存(transient) : 当事务提交时,不需要将对象信息持久化到数据库中的对象。对暂存对象的修改不会在数据库中体现。
Ø 持久化(persistent) :当事务提交时,需要将对象信息持久化到数据库中的对象。对持久化对象的修改将会在数据库中体现。
在两种情况下,一个对象要成为可持久化的:该对象是一次查询的结果(而且该查询不是在read-only 策略下执行的)或者该对象是使用JDO Database 实例的create(java.lang.Object) 或update(java.lang.Object) 方法添加到数据库的。所有不可持久化的对象都是暂存对象。当事务提交或回滚后,所有可持久化对象都变为暂存对象。
在独立Java 应用中,使用begin() ,commit() 和rollback() 方法来控制事务。如果一个持久化对象在事务内部被修改,在提交阶段所有的修改会更新到数据库。如果事务回滚,对数据库数据所做的所有更改将撤销。当事务完成后,该对象由持久化转入暂存状态,因此,如果在两个不同的事务中使用同一个对象,必须再一次执行查询。
对象的持久化与暂存状态是相对于事务所属的JDO Database 实例来说的。如果一个对象在某一JDO Database 实例中是可持久化的,在另一个JDO Database 实例中调用方法isPersistent(java.lang.Object) 时返回false 。将一个对象持久化到两个数据库中可以通过在一个数据库中查询并在另一个数据库中重新构建来实现。
4.2.2          执行OQL查询
OQL 查询用于从数据库中查询对象。OQL 查询类似于SQL 查询,但在查询语句中不是使用SQL 名称而是对象名称,而且OQL 不需要联合查询(join) 语句。例如,如果对象以TestObject 类型加载,则OQL 查询使用“FROM TestObject ”语句而不用关心该对象所对应的数据库表名称为”test”,”test_object” 或其他。在SQL 中,如果需要查找关联表必须使用SQL 的关联查询来实现;在OQL 中,加载关联对象时Castor 会自动完成关联查询。下述代码使用OQL 从产品(Product) 数据表中查询属于某一组的所有对象。注意:产品和产品组是关联对象,使用JDBC 查询时需要使用join 联合查询:

OQLQuery     oql;
QueryResults results;
// Explicitly begin transaction
db.begin();
// Construct a new query and bind its parameters
oql = db.getOQLQuery("SELECT p FROM Product p WHERE Group=$1");
oql.bind(groupId);
// Retrieve results and print each one
results = oql.execute();
while (results.hasMore()) {
 System.out.println(results.next());
}
// Explicitly close the QueryResults
results.close();
// Explicitly close the OQLQuery
oql.close();
// Explicitly commit transaction
db.commit();
db.close();

下述代码使用上面代码的查询获取所有的产品,并修改这些产品的价格减少到原有价格的25%然后重新写入数据库。

OQLQuery     oql;
QueryResults results;
// Explicitly begin transaction
db.begin();
// Construct a new query and bind its parameters
oql = db.getOQLQuery("SELECT p FROM Product p WHERE Group=$1");
oql.bind(groupId);
// Retrieve results and mark up each one by 25%
Product prod;
while (results.hasMore()) {
 prod = (Product) results.next();
 prod.markDown(0.25);
 prod.setOnSale(true);
}
// Explicitly close the QueryResults
results.close();
// Explicitly close the OQLQuery
oql.close();
// Explicitly commit transaction
db.commit();
db.close();

正如上述代码所示,在Castor JDO中,一次查询分为三个步骤。首先使用OQL语句从数据库中查询对象;然后,如果存在任何查询参数,第二步是绑定这些参数,有限的参数按照其顺序依次绑定(如$1为第一个参数,$2为第二个参数,依次类推)。第三步是执行查询并获得类型为 org.exolab.castor.jdo.QueryResult的查询结果。
一个查询在创建后可以执行多次。每次执行后,该查询所绑定的参数将会丢失必须再次进行绑定。查询的结果可以在执行新一次查询后继续使用。Castor JDO也支持调用数据库存储过程:
oql = db.getOQLQuery("CALL sp_something($) AS myapp.Product");
上面的语句中sp_something是一个存储过程并返回一个或多个ResultSets,这些结果集的返回顺序与Castor生成的SELECT语句“SELECT p FROM myapp.Product p”相同。对于没有关系的对象,返回顺序为:主键,然后按Mapping映射文件中指定的字段顺序排序。
4.2.3          创建持久化对象
JDO Database 类中的create(java.lang.Object) 实例方法用于在数据库中构建一个新的对象,以JDO 术语来说是将暂存对象持久化。使用create() 方法构造的对象在事务提交后仍存在于数据库中;如果事务回滚则该对象将从数据库中删除。如果在数据库中创建具有相同主键的对象将会抛出异常。下述代码使用前述查询的产品组创建一个新的产品:

Database db = ...;
db.begin();        
//load product group
ProductGroup furnitures = db.load(...);
// Create the Product object
Product prod;
prod = new Product();
prod.setSku(5678);
prod.setName("Plastic Chair");
prod.setPrice(55.0 );
prod.setGroup(furnitures);
// Make it persistent
db.create(prod);
db.commit();   

4.2.4          删除持久化对象
JDO Database 类中的remove(java.lang.Object) 方法从数据库中删除持久化数据对象。如果一个对象被删除,则该对象对所有的事务都不可见。如果事务提交,该对象将从数据库中彻底删除;如果事务回滚,则该对象仍然存在于数据库中。当尝试删除一个非持久化的对象时将抛出异常。下面的代码删除前述构建的产品实例:

Database db = ...;
db.begin();        
// load the Product instance with sku = 5678
Product prod = db.load (Product.class, new Integer(5678);
// delete the Product instance
db.create(prod);
db.commit();  

4.2.5          更新持久化对象
org.exolab.castor.jdo.Database 类中没有特定的方法用于更新现有的持久化对象。更新持久化对象的过程可以通过加载需要更新的对象,修改其属性然后提交事务实现。Castor JDO 会自动确定要提交的对象是否存在变更,如果存在则将变更持久化到数据库。下述代码加载前述创建的产品实例,然后变更其产品描述信息,最后提交事务将变更持久化回数据库。

Database db = ...;
db.begin();        
// load the Product instance with sku = 5678
Product prod = db.load (Product.class, new Integer(5678);
// change the object properties
prod.setDescription("New plastic chair");
//commit the transaction
db.commit();   

4.3同时使用JDO和XML
Castor JDO 与Castor XML 的结合可以使XML 作为数据库数据的输入和输出形式。下面的代码用持久化和暂存对象描述了一次账户转存操作。在这次金融操作中存在两个账户对象,操作将一个账户的金额部分转入另一个账户。示例中使用Transfer 描述一个暂存的对象,该对象在数据库中并没有对应的记录。操作完成后使用Castor XML Marshaller 将这次账户转存操作的描述用XML 文档输出。

Transfer trans;
Account from;
Account to;
OQLQuery oql;
trans = new Transfer();
// Construct a query and load the two accounts
oql = db.getOQLQuery("SELECT a FROM Account a WHERE Id=___FCKpd___169quot;);
oql.bind(fromId);
from = oql.execute().nextElement();
oql.bind(toId);
to = oql.execute().nextElement();
// Move money from one account to the other
if (from.getBalance() >= amount) {
 from.decBalance(amount);
 to.incBalance(amount);
 trans.setStatus(Transfer.COMPLETE);
 trans.setAccount(from);
 trans.setAmount(amount);
} else {
 // Report an overdraft
 trans.setStatus( Transfer.OVERDRAFT );
}
// Produce an XML describing the transfer
Marshaller.marshal(trans, outputStream); 

上述代码生成的XML文档如下所示:

<?xml version="1.0"?>
<report>
 <status>Completed</status>
 <account id="1234-5678-90" balance="50"/>
 <transfer amount="49.99"/>
</report>

5.       JDO数据库配置文件
默认方式下,Castor JDO 访问一个特定的数据库时使用数据库配置文件获取配置信息。该配置文件详细描述了从某一数据库服务器上获取一个连接的信息以及在该数据库服务器上的数据表与Java 类之间的映射信息。用户也可以使用JDOConfFactory 来编程设定数据库配置。
5.1JDO数据库配置Schema定义
Castor JDO 数据库配置XML Schema 定义如下:
<?xml version="1.0" encoding="UTF-8"?>
< xsd:schema xmlns:xsd =" http://www.w3.org/2001/XMLSchema "
 targetNamespace =" http://castor.org/JDO "
 xmlns =" http://castor.org/JDO " >
 
  < xsd:element name =" jdo-conf">
   < xsd:complexType >
     < xsd:sequence >
       < xsd:element ref =" database " minOccurs =" 1 " maxOccurs =" unbounded " />
       < xsd:element ref =" transaction-demarcation " minOccurs =" 0 " maxOccurs =" 1 " />
     </ xsd:sequence >
     < xsd:attribute name =" name " type =" xsd:string " use =" optional " default =" jdo-conf " />
   </ xsd:complexType >
  </ xsd:element >
 
  < xsd:element name =" database">
   < xsd:complexType >
     < xsd:sequence >
       < xsd:choice >
         < xsd:element ref =" driver " />
         < xsd:element ref =" data-source " />
         < xsd:element ref =" jndi " />
       </ xsd:choice >
       < xsd:element ref =" mapping " minOccurs =" 1 " maxOccurs =" unbounded " />
     </ xsd:sequence >
     < xsd:attribute name =" name " type =" xsd:ID " use =" required "/>
     < xsd:attribute name =" engine " type =" xsd:string " use =" optional " default =" generic " />
   </ xsd:complexType >
  </ xsd:element >
 
  < xsd:element name =" driver">
   < xsd:complexType >
     < xsd:sequence >
       < xsd:element ref =" param " minOccurs =" 0 " maxOccurs =" unbounded "/>
     </ xsd:sequence >
     < xsd:attribute name =" url " type =" xsd:string " use =" required " />
     < xsd:attribute name =" class-name " type =" xsd:string " use =" required " />
   </ xsd:complexType >
  </ xsd:element >
 
  < xsd:element name =" data-source">
   < xsd:complexType >
     < xsd:sequence >
       < xsd:element ref =" param " minOccurs =" 0 " maxOccurs =" unbounded "/>
     </ xsd:sequence >
     < xsd:attribute name =" class-name " type =" xsd:string " use =" required " />
   </ xsd:complexType >
  </ xsd:element >
 
  < xsd:element name =" jndi">
   < xsd:complexType >
      < xsd:attribute name =" name " type =" xsd:string " use =" required " />
   </ xsd:complexType >
  </ xsd:element >
 
  < xsd:element name =" mapping">
   < xsd:complexType >
     < xsd:attribute name =" href " type =" xsd:string " use =" required " />
   </ xsd:complexType >
  </ xsd:element >
 
  < xsd:element name =" transaction-demarcation">
   < xsd:complexType >
     < xsd:sequence >
       < xsd:element ref =" transaction-manager " minOccurs =" 0 " maxOccurs =" 1 " />
     </ xsd:sequence >
     < xsd:attribute name =" mode " type =" xsd:string " use =" required "/>
   </ xsd:complexType >
  </ xsd:element >
 
  < xsd:element name =" transaction-manager">
   < xsd:complexType >
     < xsd:sequence >
        < xsd:element ref =" param " minOccurs =" 0 " maxOccurs =" unbounded "/>
     </ xsd:sequence >
     < xsd:attribute name =" name " type =" xsd:string " default =" local " />
   </ xsd:complexType >
  </ xsd:element >
 
  < xsd:element name =" param">
   < xsd:complexType >
     < xsd:attribute name =" name " type =" xsd:string " use =" required " />
     < xsd:attribute name =" value " type =" xsd:string " use =" required " />
   </ xsd:complexType >
  </ xsd:element >
</ xsd:schema >
 
Castor 名称空间 URI : http://castor.org/ 。用户如果希望校验JDO 数据库配置文件,使用如下设定:

 <!DOCTYPE jdo-conf PUBLIC "-//EXOLAB/Castor JDO Configuration Schema Version 1.0//EN"
                             "http://castor.org/jdo-conf.xsd">

Castor JDO 数据库配置XML 文档举例如下:
<?xml version="1.0"?>
< jdo-conf >
   < database name =" Supplier-Update " engine =" oracle ">
          < driver class-name =" oracle.jdbc.driver.OracleDriver " url =" jdbc:oracle:thin:@192.168.0.1:1521:MyDB ">
                 < param name =" user " value =" test "/>
                 < param name =" password " value =" test "/>
          </ driver >
          < mapping href =" TestMapping.xml "/>
< mapping href =" OtherMapping.xml "/>
   </ database >
 
   < transaction-demarcation mode =" local ">
          < transaction-manager name =" local "/>
   </ transaction-demarcation >
</ jdo-conf >
 
J2EE 配置方式举例:
  <?xml version="1.0"?>
  < jdo-conf >
    < database name =" ebiz " engine =" oracle ">
       < jndi name =" java:comp/env/jdbc/mydb "/>
       < mapping href =" ebiz.xml "/>
    </ database >
    < transaction-demarcation mode =" global ">
       < transaction-manager name =" jndi ">
          < param name =" jndiEnc " value =" java:comp/env/TransactionManager "/>
       </ transaction-manager >
    </ transaction-demarcation >
  </ jdo-conf >
如上例所示,Castor JDO 使用数据库配置文件访问特定数据库,在配置中< database > 节点的 name 属性指定了访问该数据库的名称,其子节点< mapping> 指定了该数据库上的对象关系映射信息. engine 属性指定了数据库服务的类型。不同的数据库系统Castor 为 engine 属性定义了不同的值,Castor 支持的数据类型的 engine 名称如下表所示:

Engine 名称
数据库类型
Engine 名称
数据库类型
db2
DB2
mysql
MySQL
derby
Derby
oracle
Oracle7-Oracle 10g
generic
Generic JDBC Support
postgresql
PostgreSQL
hsql
Hypersonic SQL
sapdb
SAP DB/MaxDB
informix
Informix
Sql-server
Microsoft SQL Server
instantdb
InstantDB
sybase
Sybase 11
interbase
Interbase
pointbase
Borland Pointbase
progress
Progress RDBMS
 
 

注意:Castor不支持SunJDBC-ODBC桥,因此不支持MS Access
5.2 JDO数据库配置概述
JDO数据库配置中存在三种方式设定数据库连接:设定JDBC驱动的URL;设定JDBC DataSource数据源;以JNDI方式查找JDBC数据源。Castor应用在J2EE应用服务器中时,推荐使用JNDI查找(参考jndi节点),让应用服务器管理连接池和分布式事务。
同一database配置中允许指明多个数据映射定义文件,两个数据库配置可以共享同一个数据映射定义文件。考虑到并发和数据一致性的原因,两个数据库配置不应该使用重叠的映射文件。理想情况是每一个数据库服务器使用一个数据库配置。
数据映射定义文件使用URL指定路径,通常情况是使用file:URL。如果数据库配置文件与映射定义文件在同一个目录下,则可以使用相对路径URL。相对路径URL在数据库配置文件和数据映射定义文件从JAR文件获取且位于相同的类路径(ClassPath)下时也可以使用。
<driver>节点指定从数据库服务器获取一个新连接所使用的JDBC驱动类型( class-name)和位置( url),其他属性设定使用< param>节点。
下面是Oracle8i JDBC驱动 (type 4)的配置示例:

  < jdo-conf >         
    < database name =" ebiz " engine =" oracle ">
       < driver class-name =" oracle.jdbc.driver.OracleDriver "
               url =" jdbc:oracle:thin:@host:port:SID ">
          < param name =" user " value =" scott " />
          < param name =" password " value =" tiger " />
       </ driver >
       ...
    </ database >
    ...
 </jdo-conf>

<data-source>节点指以JDBC 数据源的方式获取数据库连接。DataSource在JDBC2.0规范中定义。 class-name属性指定JDBC数据源的实现类全名称。数据源的属性配置使用类似Java Bean的getter/setter方法由 <param>节点配置设定。下面是PostgreSQL 7.1 DataSource配置示例:

  < jdo-conf >
    < database name =" ebiz " engine =" oracle ">
       < data-source class-name =" org.postgresql.PostgresqlDataSource ">
          < param name =" serverName " value =" host " />
          < param name =" portNumber " value =" 5432 " />
          < param name =" databaseName " value =" db " />
          < param name =" user " value =" user " />
          < param name =" password= " value =" secret " />
       </ data-source >
       ...
    </ database >
    ...
 </jdo-conf>

<jndi>节点指定使用JNDI查找方式获取JDBC数据源实例。下面是J2EE数据源设定的示例:

  < jdo-conf >
    < database name =" ebiz " engine =" oracle ">
       < jndi name =" java:comp/env/jdbc/mydb " />
    </ database >
    ...
</jdo-conf>

5.3事务声明
Castor 在使用JDO 操作数据库数据时,使用JDO 配置文件配置事务声明。 <transaction-demarcation>节点的mode属性值可以设置为local或者global,分别代表着两种事务处理模式。
5.3.1          本地事务(Local Mode
当Castor JDO 在独立的Java 应用中使用时,需要Castor 控制事务的声明, <transaction-demarcation>节点的配置如下:

<transaction-demarcation mode="local" />

5.3.2          全局事务(Global Mode
当Castor 运行于J2EE 应用服务器时,如果使用全局事务(XA 事务), <transaction-demarcation>节点的配置如下:

<transaction-demarcation mode="global">
   <transaction-manager name="jndi" />
</transaction-demarcation>

在此模式下,<transaction-manager> 节点用于确定J2EE容器用于控制这些事务的事务管理器。Castor支持的事务管理器如下表所示:
管理器名称
jndi
TM looked up in the JNDI ENC
websphere
IBM WebSphere 4 and previous releases
websphere5
IBM WebSphere 5
websphere51
IBM WebSphere 5.1
jotm
JOTM
除了设定事务管理其名称外,可以在<transaction-manager>节点内添加<param>子节点,用于设置事务管理器的名称/键值对属性。注意:目前只有JNDI事务管理器支持此种属性设定。在次上下文中,使用jndiEnc属性可以指定使用那种JNDI ENC来查找事务管理器。配置示例如下:

 <transaction-demarcation mode="global">
     <transaction-manager name="jndi">
        <param name="jndiEnc" value="java:comp/env/TransactionManager"/>
     </transaction-manager>
 </transaction-demarcation>

5.4不同数据库的配置示例

 ...
 <!-- JDBC data source for Sybase using jConnect -->
 <data-source class-name="com.sybase.jdbc2.jdbc.SybDataSource">
    <param name="user" value="user" />
    <param name="password value="secret" />
    <param name="portNumber" value="4100" />
    <param name="serverName" value="host" />
 </data-source>
 ...

 ...
 <!-- JDBC data source for PostgreSQL -->
 <data-source class-name="org.postgresql.PostgresqlDataSource">
     <param name="serverName" value="host" />
     <param name="portNumber" value="5432" />
     <param name="databaseName" value="db" />
     <param name="user" value="user" />
     <param name="password" value="secret" />
   </data-source>
   ...

 ...
 <!-- JDBC driver definition for 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>
 ...

 ...
 <!-- JDBC data source for mySQL -->
 <driver class-name="com.mysql.jdbc.Driver"
          url="jdbc:mysql:/localhost:2206/test">
    <param name="user" value="scott" />
    <param name="password" value="tiger" />
 </driver>
 ...

 ...
 <!-- JDBC data source for InstantDB -->
 <driver class-name="org.enhydra.instantdb.jdbc.idbDriver"
          url="jdbc:idb:C://castor-1.0//db//test//test.prp">
    <param name="user" value="" />
    <param name="password" value="" />
 </driver>
 ...

5.5以编程方式配置Castor JDO
很多应用系统使用不同的用户账户来连接数据库,为实现此种需求,Castor 提供了帮助类JDOConfFactoryJDOManager.loadConfiguration(org.exolab.castor.jdo.conf.JdoConf) 方法。下面的代码示例展示了在不使用数据库XML 配置文件的情况下设定JDO 数据库配置:

 private static final String DRIVER = "oracle.jdbc.driver.OracleDriver";
 private static final String CONNECT = "jdbc:oracle:thin:localhost:1521:SID";
 private static final String USERNAME = "scott";
 private static final String PASSWORD = "tiger";
 private static final String MAPPING = "mapping.xml";
 private static final String DATABASE = "mydb";
 private static final String ENGINE = "oracle";
  // create driver configuration
 org.castor.jdo.conf.Driver driverConf =
      JDOConfFactory.createDriver(DRIVER, CONNECT, USERNAME, PASSWORD);
  // create mapping configuration
 org.castor.jdo.conf.Mapping mappingConf =
      JDOConfFactory.createMapping(getClass().getResource(MAPPING).toString());
  // create database configuration
 org.castor.jdo.conf.Database dbConf =
      JDOConfFactory.createDatabase(DATABASE, ENGINE, driverConf, mappingConf);
  // create and load jdo configuration
 JDOManager.loadConfiguration(JDOConfFactory.createJdoConf(dbConf));
  // Construct a new JDOManager for the database
 jdoManager = JDOManager.createInstance(DATABASE);
  // Obtain a new database
 Database db = jdoManager.getDatabase();

下面代码以另一种方式通过使用org.exolab.castor.jdo.conf.JdoConf来配置JDBC 2.0 DataSource:

 private static final String DS = "oracle.jdbc.pool.OracleConnectionCacheImpl";
 private static final String CONNECT = "jdbc:oracle:thin:localhost:1521:SID";
 private static final String USERNAME = "scott";
 private static final String PASSWORD = "tiger";
 private static final String MAPPING = "mapping.xml";
 private static final String DATABASE = "mydb";
 private static final String ENGINE = "oracle";
  // setup properties for datasource configuration
 Properties props = new Properties();
 props.put("URL", CONNECT);
 props.put("user", USERNAME);
 props.put("password", PASSWORD);       
  // create datasource configuration
 org.castor.jdo.conf.DataSource dsConf =
      JDOConfFactory.createDataSource(DS, props);          
  // create mapping configuration
 org.castor.jdo.conf.Mapping mappingConf =
      JDOConfFactory.createMapping(getClass().getResource(MAPPING).toString());  
  // create database configuration
 org.castor.jdo.conf.Database dbConf =
      JDOConfFactory.createDatabase(DATABASE, ENGINE, dsConf, mappingConf);
  // create and load jdo configuration
 JDOManager.loadConfiguration(JDOConfFactory.createJdoConf(dbConf));
  // Construct a new JDOManager for the database
 jdoManager = JDOManager.createInstance(DATABASE);
  // Obtain a new database
 Database db = jdoManager.getDatabase();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值