13.5.Apache OJB
13.5. Apache OJB
Apache OJB (http://db.apache.org/ojb) 提供了不同的API级别,例如ODMG和JDO。 除了通过JDO支持OJB,Spring同样为OJB的低层次的 PersistenceBroker
API作为数据访问提供支持。 相应的整合与支持的类位于 org.springframework.orm.ojb
包中。
13.5.1. 在Spring环境中建立OJB
与Hibernate或者JDO相比,OJB并没有使用工厂模式进行资源管理,PersistenceBroker
必须通过从一个静态的 PersistenceBrokerFactory
类中获得。 这个工厂类根据一个位于classpath目录下的OJB.properties配置文件进行初始化。
除了对OJB的默认的初始化方式进行支持,Spring还提供了一个 LocalOjbConfigurer
的类。 它允许使用受到Spring管理的 DataSource
实例作为OJB链接的提供者。 DataSource
实例则在OJB资源描述器(配置文件)中进行描述,通过"jcd-alias"的定义完成:每个别名都与受Spring管理的同名的bean匹配。
<beans> <bean id="dataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <bean id="ojbConfigurer"/> ... </beans>
<descriptor-repository version="1.0"> <jdbc-connection-descriptor jcd-alias="dataSource" default-connection="true" ...> ... </jdbc-connection-descriptor> ... </descriptor-repository>
一个 PersistenceBroker
此时可以通过标准的OJB的API打开,并指定一个对应的“PBKey”。 这通常通过对应的"jcd-alias"定义来完成(或者依赖于默认的连接)。
13.5.2. PersistenceBrokerTemplate
和 PersistenceBrokerDaoSupport
每个基于OJB的DAO都将通过一个"PBKey"以bean方式进行配置,配置通过Setter注入方式完成。这样的DAO能够通过OJB的静态的 PersistenceBrokerFactory
类直接操作普通的OJB API进行编程。 当然你可以更愿意使用Spring的 PersistenceBrokerTemplate
:
<beans> ... <bean id="myProductDao"> <property name="jcdAlias" value="dataSource"/> <!-- can be omitted (default) --> </bean> </beans>
public class ProductDaoImpl implements ProductDao { private String jcdAlias; public void setJcdAlias(String jcdAlias) { this.jcdAlias = jcdAlias; } public Collection loadProductsByCategory(final String category) throws DataAccessException { PersistenceBrokerTemplate pbTemplate = new PersistenceBrokerTemplate(new PBKey(this.jcdAlias); return (Collection) pbTemplate.execute(new PersistenceBrokerCallback() { public Object doInPersistenceBroker(PersistenceBroker pb) throws PersistenceBrokerException { Criteria criteria = new Criteria(); criteria.addLike("category", category + "%"); Query query = new QueryByCriteria(Product.class, criteria); List result = pb.getCollectionByQuery(query); // do some further stuff with the result list return result; } }); } }
一个回调的实现能够有效地在任何OJB数据访问中使用。PersistenceBrokerTemplate
会确保当前的 PersistenceBroker
对象的正确打开和关闭,并自动参与到事务管理中去。 Template实例不仅是线程安全的,同时它也是可重用的。因而他们可以作为外部对象的实例变量而被持有。对于那些简单的诸如 getObjectById
、getObjectByQuery
、store
和 delete
操作的调用,PersistenceBrokerTemplate
提供可选择的快捷函数来替换这种回调的实现。 不仅如此,Spring还提供了一个简便的 PersistenceBrokerDaoSupport
基类,这个类提供了 setJcdAlias
方法来接受一个OJB JCD的别名,同时提供了 getPersistenceBrokerTemplate
方法给子类使用。 综合了这些,对于那些典型的业务需求,就有了一个非常简单的DAO实现:
public class ProductDaoImpl extends PersistenceBrokerDaoSupport implements ProductDao { public Collection loadProductsByCategory(String category) throws DataAccessException { Criteria criteria = new Criteria(); criteria.addLike("category", category + "%"); Query query = new QueryByCriteria(Product.class, criteria); return getPersistenceBrokerTemplate().getCollectionByQuery(query); } }
作为不使用Spring的 PersistenceBrokerTemplate
来实现DAO的替代解决方案,你依然可以通过在原生OJB API的级别对那些基于Spring的DAO进行编程,此时你必须明确地打开和关闭一个 PersistenceBroker
。 正如在相应的Hibernate章节描述的一样,这种做法的主要优点在于你的数据访问代码可以在整个过程中抛出checked exceptions。PersistenceBrokerDaoSupport
为这种情况提供了多种函数支持,包括获取和释放一个具备事务管理功能的 PersistenceBroker
和相关的异常转化。
13.5.3. 事务管理
将事务管理纳入到Service操作的执行中,你可以使用Spring通用的声明式的事务管理功能,例如:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> ... <bean id="myTxManager"> <property name="jcdAlias" value="dataSource"/> </bean> <bean id="myProductService"> <property name="productDao" ref="myProductDao"/> </bean> <aop:config> <aop:pointcut id="productServiceMethods" expression="execution(* product.ProductService.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/> </aop:config> <tx:advice id="txAdvice" transaction-manager="myTxManager"> <tx:attributes> <tx:method name="increasePrice*" propagation="REQUIRED"/> <tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/> <tx:method name="*" propagation="SUPPORTS" read-only="true"/> </tx:attributes> </tx:advice> </beans>
注意OJB的 PersistenceBroker
级别的API并不跟踪加载的对象的变化。 因而,一个 PersistenceBroker
的事务非常有必要成为一个简单的在 PersistenceBroker
级别的事务而仅仅加入一个为持久对象而设置的一级缓存。 此时,懒式加载无论在 PersistenceBroker
打开或者关闭时都将工作得很好。这一点与Hibernate和JDO相比有很大得不同。(懒式加载仅仅对于 Session
或者 PersistenceManager
各自保持打开时才有效)。
PersistenceBrokerTransactionManager
能够将一个OJB事务暴露给访问相同的JDBC DataSource
的JDBC访问代码。 前提条件是,所需要暴露事务的 DataSource
必须被明确指定,它无法被自动检测到。