用JDO替代CMP的应用
在大多数使用EJB的项目中,O/R Mapping一直是Java开发者关注的问题。自从有了CMP(Container Managed Persistence),数据库映射需要做的工作轻松多了。然而,CMP仍然有不完善的地方??针对不同的应用服务器,CMP的映射描述文件不同,这在一定程度上阻碍了EJB的移植;CMP/CMR与数据表的映射关系比较复杂。经笔者测试,使用Castor JDO(Java数据对象)比使用CMP性能有很大的提高,而且能满足大多数应用的需求。
关于Castor JDO
Castor JDO是一个以RDBMS为中心的开放源码项目,虽然它与Sun的JDO有很多相似之处,但没有完全遵循JSR规范。一些主要技术上的差异使它与Sun的JDO规范并不十分相符。每一个持久对象在Castor中都有一个被观察的数据锁,这意味着事物的超时和死锁可以不被视为数据锁定。而Sun的JDO规范却隐藏了锁的细节。
内部的Castor JDO对每个事物活动的持久对象都提供一个数据锁的拷贝(包括缓存)维护。Sun的JDO未明确要求每一个事物的每一个对象用缓存,但它含蓄地要求具有字节码修饰者,而Castor却不需要。
Castor还提供一些Sun的JSR规范中没有提到的其它特性,比如键值生成器(常用于ID自动生成)、长时事务支持和OQL等。
Castor JDO和EJB CMP
JDO和EJB Bean之间的关系很难用谁比谁更好来形容。实体Bean可以治理自身的持久性(EJB规范称为Bean治理的持久性或BMP),也可以依靠EJB容器来治理它(称为容器治理的持久性或CMP)。
对于BMP,实体Bean可以用Castor JDO作为持久性机制,或者使用其它的办法,比如直接使用JDBC作为持久性机制。对于CMP,EJB容器供给商可以在Castor JDO之上实施CMP,这样Castor JDO就被用来作为实体Bean的持久机制。
假如开发者需要EJB的治理生存周期、安全性、“一次开发随意部署”的承诺和分布式商业应用等特性,那么EJB是正确的选择。然而事实上,Castor的简洁、开放性、更多设计上的自由度和与Castor XML整合等特性,让人有充分的理由选择Castor JDO。庆幸的是,我们可结合EJB和Castor JDO的优点来弥补它们各自的短处,这就是本文的目的。
Castor JDO结合SessionBean使用
选择应用服务器
目前只有JBoss有支持Castor JDO的包。Castor会在将来的版中提供对J2EE的支持。笔者使用JBoss-2.4.9作为测试。假如选择Castor JDO完全替代CMP,可以不考虑使用支持最新CMP版本的应用服务器。
选择Castor JDO
为了获得最新版本的支持,可以选择最新的Castor JDO包。笔者测试时使用的版本是0.9.4。
配置JBoss
1.修改conf/default/jboss.jcml文件
<!-增加JDBC驱动-->
<mbean code="org.jboss.jdbc.JdbcProvider" name="DefaultDomain:service=JdbcProvider">
<attribute name="Drivers">Oracle.jdbc.
driver.OracleDriver,org.hsqldb.jdbcDriver</attribute>
</mbean>
...
<!--配置JDBC数据源-->
<mbean code="org.jboss.jdbc.XADataSourceLoader"
name="DefaultDomain:service=XADataSource,name=NewsDS">
<attribute name="PoolName">NewsDS</attribute>
<attribute name="DataSourceClass">org.jboss.pool.j
dbc.xa.wrapper.XADataSourceImpl</attribute>
<attribute name="Properties"></attribute>
<attribute name="URL">jdbc:oracle:thin:@192.168.1.7:1521:NEWS</attribute>
<attribute name="GCMinIdleTime">1200000</attribute>
<attribute name="JDBCUser">scott</attribute>
<attribute name="MaxSize">10</attribute>
<attribute name="PassWord">tiger</attribute>
...
</mbean>
...
<!-在文件最后配置CastorJDO-->
<mbean code="org.jboss.jdo.castor.CastorJDOImpl"
name="DefaultDomain:service=CastorJDO,name=castortestnews">
<attribute name="Configuration">file:../jdo/conf/database.xml</attribute>
<attribute name="JndiName">jdo/castortestnews</attribute>
<attribute name="LockTimeout">10000</attribute>
<attribute name="LoggingEnabled">true</attribute>
<attribute name="CommonClassPath">false</attribute>
<attribute name="AutoStore">false</attribute>
<!-Castor JDO新版本中提供连接池-->
<attribute name="DatabasePooling">true</attribute>
</mbean>
2.修改conf/default/standardjaws.xml文件
<datasource>java:/NewsDS</datasource>
<type-mapping>Oracle8</type-mapping>
<debug>true</debug>
3.拷贝必要的jar包到lib/ext目录下
这些包包括:Castor JDO包castor-0.9.4.jar、JBoss2.4.x的Castor JDO补丁包castorjdoplugin.jar、JDBC驱动(笔者使用的是Oracle 8.1.7)classes12.zip、XML解析包xerces-J_1.4.0.jar(笔者使用的是Castor推荐的xerces版本)。
配置Castor JDO
增加%JBOSS_HOME%jdoconfdatabase.xml文件,文件代码如下:
<!DOCTYPE databases PUBLIC "-//EXOLAB/Castor JDO Configuration DTD Version 1.0//EN"
"http://castor.exolab.org/jdo-conf.dtd">
<database name="news" engine="oracle">
<!-下面的jndi name与standardjaws.xml中的datasource对应-->
<jndi name="java:/NewsDS" />
<!--路径可以由读者指定,但父目录必须是%JBOSS_HOME%-->
<mapping href="../jdo/conf/mapping.xml" />
</database>
安装Ant
使用Ant编译部署EJB应用,可以下载安装Ant的最新版本(笔者使用的是Ant-1.5.1)。
在SessionBean中封装JDO的方法,可以参考Castor的文档。注重,作为参数传递的JDO Bean,需要实现Java串行化接口。封装JDO的代码如下:
//ejbCreate方法中查询JDO
ctx = new InitialContext();
jdo = (DataObjects) ctx.lookup("java:comp/env/jdo/CastortestnewsJDO");
//创建新对象,增加数据表中的一行
/**每一个查询或更新的方法打开新的db连接,使用后关闭,不关闭的连接会导致TransactionNotInProg
ress异常*/
db = jdo.getDatabase();
auxType.setAuxDesc(auxDesc);
db.create(auxType);
db.close();
在其它应用服务器上使用Castor JDO
针对不同的应用服务器,需要增加一个Castor JDO JNDI绑定的服务,为Castor JDO配置参数。例如,JBoss增加了一个JMX MBean的服务,提供了JBoss 实现Castor JDO MBean绑定服务的源码。