测试环境: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管理事务的配置就写完了很简单吧