spring管理事务详解

时间:2022-05-05 20:34:58

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