这篇文章主要探讨怎么用Spring来装配组件及其事务管理。在J2EE工程里连接到一个简单的数据库并不是什么难题,但是如果要综合组装企业类的组件就变得复杂了。一个简单的组件有一个或多个数据库支撑,所以,我们说到整合两个或多个的组件时,我们希望能够维持跨组件的许多数据库的运作的原子性。
J2EE提供了这些组件的容器,可以保证处理的原子性和独立性。在没有J2EE的情况下我们可以用Spring。Spring基于IoC模式(即反转模式),不仅可以配置组件服务,还可以配置相应的方法。为了更好的实现本文的目的,我们使用Hibernate来做相应的后台开发。
装配组件事务
假设在组件库里,我们已经有一个审核组件(audit component),里面有可以被客户端调用的方法。接着,当我们想要构建一个处理订单的体系,我们发现设计需要的OrderListManager组件服务同样需要审核组件服务。OrderListManager创建和管理订单,每一个服务都含有自己的事务属性。当这时调用审核组件,就可以把OrderListManager的处理内容传给它。也许将来新的业务服务(business service)同样需要审核组件,那这时它调用的事务内容已经不一样了。在网络上的结果就是,虽然审核的功能保持不变,但是可以和别的事件功能组合在一起,用这些方法属性来提供不同的运行时的处理参数。
在图1中有两个分开的调用流程。在流程1里,如果客户端含有一个TX内容,OrderListManager 要由一个新的TX开始或者参与其中,取决于客户端在不在TX里以及OrderListManager方法指定的TX属性。这在它调用AuditManager方法的时候仍然适用。
图1. 装配组件事务
EJB体系通过装配者声明正确的事务属性来获得这种适应性。我们不是在探讨是否声明事务管理,因为这会使运行时的事务参数代码发生改变。几乎所有的J2EE工程提供了分布的事务管理来配合提交协议例如X/Open XA specification。
现在的问题是我们能不能不用EJB来获得相同的功能?Spring是其中一种解决方案。来看一下Spring如何处理这样的问题:
用Spring来管理事务
我们将看到的是一个轻量级的事务机制,实际上,它可以管理组件层的事务集成。Spring就是如此。它的优点是我们可以不用捆绑在J2EE的服务例如JNDI数据库。最棒的是如果我们想把这个事务机制与已经存在的J2EE框架组合在一起,没有任何问题,就好像我们找到了杠杆中完美的支撑点一样。
Spring的另一个机制是使用了AOP框架。这个框架使用了一个可以使用AOP的Spring bean factory。在Spring特定的配置文件applicationContext.xml里通过特定的组件层的事件来指定。
<beans>
<!-- other code goes here... -->
<bean id="orderListManager"
class="org.springframework.transaction
.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref local="transactionManager1"/>
</property>
<property name="target">
<ref local="orderListManagerTarget"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="getAllOrderList">
PROPAGATION_REQUIRED
</prop>
<prop key="getOrderList">
PROPAGATION_REQUIRED
</prop>
<prop key="createOrderList">
PROPAGATION_REQUIRED
</prop>
<prop key="addLineItem">
PROPAGATION_REQUIRED,
-com.example.exception.FacadeException
</prop>
<prop key="getAllLineItems">
PROPAGATION_REQUIRED,readOnly
</prop>
<prop key="queryNumberOfLineItems">
PROPAGATION_REQUIRED,readOnly
</prop>
</props>
</property>
</bean>
</beans>
public interface PlatformTransactionManager{
TransactionStatus getTransaction
(TransactionDefinition definition);
void commit(TransactionStatus status);
void rollback(TransactionStatus status);
}<beans>
<!-- other code goes here... -->
<bean id="transactionManager1"
class="org.springframework.orm.hibernate.
HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory1"/>
</property>
</bean>
</beans>
<beans>
<!—其他代码在这里-->
<bean id="auditManager"
class="org.springframework.transaction.
interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref local="transactionManager2"/>
</property>
<property name="target">
<ref local="auditManagerTarget"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="log">
PROPAGATION_REQUIRES_NEW
</prop>
</props>
</property>
</bean>
</beans>
public class OrderListManagerImpl
implements OrderListManager{
private AuditManager auditManager;
public Long createOrderList
(OrderList orderList){
Long orderId = orderListDAO.
createOrderList(orderList);
auditManager.log(new AuditObject
(ORDER + orderId, CREATE));
return orderId;
}
public void addLineItem
(Long orderId, LineItem lineItem)
throws FacadeException{
Long lineItemId = orderListDAO.
addLineItem(orderId, lineItem);
auditManager.log(new AuditObject
(LINE_ITEM + lineItemId, CREATE));
int numberOfLineItems = orderListDAO.
queryNumberOfLineItems(orderId);
if(numberOfLineItems > 2){
log("Added LineItem " + lineItemId +
" to Order " + orderId + ";
But rolling back *** !");
throw new FacadeException("Make a new
Order for this line item");
}
else{
log("Added LineItem " + lineItemId +
" to Order " + orderId + ".");
}
}
//其他代码在这里
}
<bean id="orderListManager"
class="org.springframework.transaction.
interceptor.TransactionProxyFactoryBean">
<property name="transactionAttributes">
<props>
<prop key="createOrderList">
PROPAGATION_REQUIRED
</prop>
<prop key="addLineItem">
PROPAGATION_REQUIRED,-com.
example.exception.FacadeException
</prop>
</props>
</property>
</bean>
<bean id="auditManager" class="org.
springframework.transaction.interceptor.
TransactionProxyFactoryBean">
<property name="transactionAttributes">
<props>
<prop key="log">
PROPAGATION_REQUIRES_NEW
</prop>
</props>
</property>
</bean>
<role rolename="manager"/><user username="admin" password="admin" roles="manager"/>

CATALINA_HOME\bin\ant test -Dtestcase=OrderListManager
OrderList orderList1 = new OrderList();
Long orderId1 = orderListManager.
createOrderList(orderList1);
log("Created OrderList with id '"
+ orderId1 + "'...");
orderListManager.addLineItem(orderId1,lineItem1);
orderListManager.addLineItem(orderId1,lineItem2);
OrderList orderList2 = new OrderList();
Long orderId2 = orderListManager.
createOrderList(orderList2);
log("Created OrderList with id '"
+ orderId2 + "'...");
orderListManager.addLineItem(orderId2,lineItem3);
orderListManager.addLineItem(orderId2,lineItem4);
//这里将抛出异常…………但是仍然要执行下去
try{
orderListManager.addLineItem
(orderId2,lineItem5);
}
catch(FacadeException facadeException){
log("ERROR : " + facadeException.getMessage());
}




<bean id="auditManager"
class="org.springframework.transaction.
interceptor.TransactionProxyFactoryBean">
<property name="transactionAttributes">
<props>
<!-- prop key="log">
PROPAGATION_REQUIRES_NEW
</prop -->
<prop key="log">
PROPAGATION_SUPPORTS
</prop>
</props>
</property>
</bean>
这是生成实例管理的效果,自从我们接触EJB以来就开始寻找杠杆的最佳位置。我们需要一个高端的应用服务器 来管理我们的our EJB组件。现在我们不用EJB服务器就达到了一样的结果,用Spring。
摘要
这篇文章介绍了J2EE里十分强大的组合之一:Spring 和 Hibernate。通过两者的有机结合,我们现在多了对Container-Managed Persistence (CMP), Container-Managed Relationships (CMR), 和生成实例管理的新选择。虽然Spring不能完全代替EJB,但是它提供了很多功能,例如一般Java程序的实例生成,使得用户可以在大部分工程中和EJB搭配使用。
我们不是要为了寻找EJB的代替品,而是对于现在的问题得出一个最理想的解决方案。我们仍然要寻找Spring 和 Hibernate组合的更多优点,这就留给我们的读者去探索了。
Resources
---文章的源代码Sample code:[下载文件]
---www.springframework.org
---www.hibernate.org
---引用的书Spring Live
---引用的书Better, Faster, Lighter Java
---引用的书Hibernate: A Developer's Notebook
---引用的书Expert One-on-One J2EE Development without EJB, 作者是 Rod Johnson 及 ---Juergen Hoeller
---Hibernate/Spring/Middlegen/XDoclet tutorial
---Hibernate-Spring
---Binildas Christudas 是一个Infosys的(CSP)的高级技术指导,也是Sun公司认证的技术人员和微软认证的专家。
英文原文地址:
http://www.onjava.com/pub/a/onjava/2005/05/18/swingxactions.html
中文地址:
http://www.matrix.org.cn/resource/article/43/43708_Spring_Hibernate.html
关键词: Hibernate Spring Transactions
你可以使用这个链接引用该篇文章 http://publishblog.blogchina.com/blog/tb.b?diaryID=2789877
[2005-07-21] Hibernate与事务管理
[2005-08-20] Hibernate(三)
[2005-07-19] Hibernate是一个开源的对象关系映射工具
[2005-08-13] Hibernate要点
[2005-07-19] Hibernate Reference