测试环境:sturts1.2+spring2.0+jdbc
数据库:oracle
之前一直对spring管理事务不是太了解,今天研究学习了总结如下:
通过spring来管理事务由三个部分组成:分别是DataSource,TransactionManager和代理机制3个部分。无论哪种配置方式,一般变化的只是代理机制这部分。这里我介绍spring管理JDBC的事务方式。
配置方式如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<!-- 定义一个数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"> </property> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"> </property> <property name="username" value="new_premain"></property> <property name="password" value="new_premain"></property> </bean>
<!-- Dao文件统计jdbcTemplate来操作数据库 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean>
<!-- 申明一个事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
<!-- 申明一个事务代理机制 加入abstract让多个业务Bean共享一个事务代理机制,当代理的业务Bean没有实现接口时设置 proxyTargetClass为true 即 Spring代理有两种方式,一种时对接口的代理,另一种是才用CGLIB代理方式,对接口的代理是JDK采用的代理方式,但在没有接口的情况下Srping通过设置proxyTargetClass等于 true来使用CGLIB代理,CGLIB是一种面向继承的代理方式。同时还有一个proxyTarget属性用来指定代理的目标对象类。
-->
<bean id="transactionProxyFactoryBean" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> <property name="transactionManager" ref="transactionManager"></property> <property name="proxyTargetClass" value="true" /> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean>
<bean id="addSourceDao" class="com.Dao.AddSourceDao"> <property name="dataSource" ref="dataSource"></property> </bean>
<!-- 对应代理的业务Bean继承代理机制 -->
<bean id="addSourceService" parent="transactionProxyFactoryBean"> <property name="target"> <bean class="com.service.AddSourceService"> <property name="addSourceDao"> <ref bean="addSourceDao" /> </property> </bean> </property> </bean>
<bean name="/login" class="com.struts.action.LoginAction"> <property name="addSourceService" ref="addSourceService"></property> </bean>
</beans>
数据库操作代码:
package com.Dao;import org.springframework.jdbc.core.support.JdbcDaoSupport;public class AddSourceDao extends JdbcDaoSupport {
public void addSchool() { String sqlOne = "insert into shools(id,CUSTOMERSID,SHOOLNAME,SHOOLTYPE,TIME) values('123123','123123','武汉理工大学','本科',to_date('2010-09-01','yyyy-mm-dd') )"; String sqlTwo = "insert into shools(id,CUSTOMERSID,SHOOLNAME,SHOOLTYPE,TIME) values('123123','123123','武汉理工大学','本科',to_date('2010-09-012','yyyy-mm-dd') )"; this.getJdbcTemplate().execute(sqlOne); this.getJdbcTemplate().execute(sqlTwo); }}
以上的事务管理是通过TransactionProxyFactoryBean代理机制来控制,下面我介绍通过tx/aop来控制事务。
上面说过了控制事务由DataSource,TransactionManager和代理机制3个部分,那么通过tx/aop来控制事务变化的也就是代理机制的变化。其它什么代码都不需要变化,变化的就是application.xml的变化了:
<?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-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd ">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"> </property> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"> </property> <property name="username" value="new_premain"></property> <property name="password" value="new_premain"></property> </bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
<!-- 这里就是变化的地方。它通知事务管理器 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" /> </tx:attributes> </tx:advice>
<aop:config>
<!-- 指明AOP的切点 --> <aop:pointcut id="allManagerMethod" expression="execution(* com.service.AddSourceService.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod" /><!-- 引用事务管理器来管理切入点的事务 -->
</aop:config>
<bean id="addSourceDao" class="com.Dao.AddSourceDao"> <property name="dataSource" ref="dataSource"></property> </bean>
<bean id="addSourceService" class="com.service.AddSourceService"> <property name="addSourceDao" ref="addSourceDao"></property> </bean>
<bean name="/login" class="com.struts.action.LoginAction"> <property name="addSourceService" ref="addSourceService"></property> </bean>
</beans>
通过tx/aop来管理事务更加方便。注意execution(* com.service.*.*(..)) 里面第一个*表示返回参数为任意类型,第二个
表示service包下的任意类,第三个*表示任意方法。括号里面的..表示方法里面的参数为任意多个参数。
好了tx/aop管理事务的配置就写完了很简单吧