1.1 Spring事务管理及方式

本文详细介绍了Spring框架中的事务管理,包括声明式事务管理与编程式事务管理。声明式事务管理通过XML配置和注解两种方式进行说明,同时介绍了事务传播行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring是SSH中的管理员,负责管理其它框架,协调各个部分的工作。今天一起学习一下Spring的事务管理。Spring的事务管理分为声明式跟编程式。声明式就是在Spring的配置文件中进行相关配置(XML和注解);编程式就是代码中添加事务,如回滚等。事务拦截器和事务自动代理方式实现原理:像Struts2一样,都是凭借强大的拦截器功能对业务逻辑方法的调用进行拦截,然后又BeanNameAutoProxyCreator自动生成事务代理,最后送事务管理器,统一管理。
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。  DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。 有声明式事务管理和编程式事务管理。
spring是靠AOP的方法拦截异常去判断是否需要事务回滚或提交的。你自己把异常给catch了,又不往上抛出 别人怎么知道你的方法是否执行正常呢。(可以抛出运行时异常就可以)
http://java.chinaitlab.com/Spring/841714_4.html
1.spring在进行声明时事务管理时,通过捕获Service层方法的DataAccessException来提交和回滚事务的,而Service层方法的DataAccessException又是来自调用DAO层方法所产生的异常.
2.我们一般在写DAO层代码时,如果继承JdbcDaoSupport 类,并使用此类所实现的JdbcTemplate来执行数据库操作,此类会自动把低层的SQLException转化成DataAccessException以及DataAccessException的子类.
3.一般在Service层我们可以自己捕获DAO方法所产成的DataAccessException,然后再抛出一个业务方法有意义的异常(ps:此异常最好继承DataAccessException),然后在Web层捕获,这样我们就可以手动编码的灵活实现通过业务方法执行的成功和失败来向用户转发不同的页面.)

下面一起看看两种(XML和注解)声明式事务的具体配置:
声明式事务
XML:
公共配置

[html]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <!-- 配置sessionFactory -->  
  2. <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  3.     <property name="configLocation">  
  4.         <value>classpath:config/hibernate.cfg.xml</value>  
  5.     </property>  
  6.     <property name="packagesToScan">  
  7.         <list>  
  8.             <value>com.entity</value>  
  9.         </list>  
  10.     </property>  
  11. </bean>  
  12.   
  13. <!-- 配置事务管理器(声明式的事务) -->  
  14. <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  15.     <property name="sessionFactory" ref="sessionFactory"></property>  
  16. </bean>  
  17.   
  18. <!-- 配置DAO -->   
  19. <bean id="userDao" class="com.dao.UserDaoImpl">  
  20.     <property name="sessionFactory" ref="sessionFactory"></property>  
  21. </bean>  


第一种,使用tx标签方式

[html]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <!-- 第一种配置事务的方式 ,tx-->  
  2. <tx:advice id="txadvice" transaction-manager="transactionManager">  
  3.     <tx:attributes>  
  4.         <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception" />  
  5.         <tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception" />  
  6.         <tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>  
  7.         <tx:method name="*" propagation="REQUIRED" read-only="true"/>  
  8.     </tx:attributes>  
  9. </tx:advice>  
  10.   
  11. <aop:config>  
  12.     <aop:pointcut id="daoMethod" expression="execution(* com.dao.*.*(..))"/>  
  13.     <aop:advisor pointcut-ref="daoMethod" advice-ref="txadvice"/>  
  14. </aop:config>  
expression="execution(* com.dao.*.*(..))"
其中第一个*代表返回值,第二*代表dao下子包,第三个*代表方法名,“(..)”代表方法参数。
第二种,使用代理方式

[html]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <!-- 第二种配置事务的方式 ,代理-->  
  2. <bean id="transactionProxy"  
  3.     class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">  
  4.     <property name="transactionManager" ref="transactionManager"></property>  
  5.     <property name="transactionAttributes">  
  6.         <props>  
  7.             <prop key="add*">PROPAGATION_REQUIRED, -Exception</prop>  
  8.             <prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop>  
  9.             <prop key="del*">PROPAGATION_REQUIRED, -Exception</prop>  
  10.             <prop key="*">PROPAGATION_REQUIRED, readOnly</prop>  
  11.         </props>  
  12.     </property>  
  13. </bean>  
  14. <bean id="userDao" parent="transactionProxy">  
  15.     <property name="target">  
  16.         <!-- 用bean代替ref的方式-->  
  17.         <bean class="com.dao.UserDaoImpl">  
  18.             <property name="sessionFactory" ref="sessionFactory"></property>  
  19.         </bean>  
  20.     </property>  
  21. </bean>  
将transactionProxy的abstract属性设置为"true",然后将具体的Dao的parent属性设置为"transactionProxy",可以精简代码。

第三种,使用拦截器

[html]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <!-- 第三种配置事务的方式,拦截器 (不常用)-->  
  2. <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">  
  3.     <property name="transactionManager" ref="transactionManager"></property>  
  4.     <property name="transactionAttributes">  
  5.         <props>  
  6.             <prop key="add*">PROPAGATION_REQUIRED, -Exception</prop>  
  7.             <prop key="modify*">PROPAGATION_REQUIRED, -Exception</prop>  
  8.             <prop key="del*">PROPAGATION_REQUIRED, -Exception</prop>  
  9.             <prop key="*">PROPAGATION_REQUIRED, readOnly</prop>  
  10.         </props>  
  11.     </property>  
  12. </bean>  
  13. <bean id="proxyFactory" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">  
  14.     <property name="interceptorNames">  
  15.         <list>  
  16.             <value>transactionInterceptor</value>  
  17.         </list>  
  18.     </property>  
  19.     <property name="beanNames">  
  20.         <list>  
  21.             <value>*Dao</value>  
  22.         </list>  
  23.     </property>  
  24. </bean>  


Spring事务类型详解:


PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。


注解:

采用注解的方式,需要注意的是,使用注解的方式需要在Spring的配置文件中加入一句话:<context:annotation-config />,其作用是开启注解的方式。具体配置如下:

[html]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <!--开启注解方式-->  
  2. <context:annotation-config />  
  3.   
  4. <!-- 配置sessionFactory -->  
  5. <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  
  6.     <property name="configLocation">  
  7.         <value>classpath:config/hibernate.cfg.xml</value>  
  8.     </property>  
  9.     <property name="packagesToScan">  
  10.         <list>  
  11.             <value>com.entity</value>  
  12.         </list>  
  13.     </property>  
  14. </bean>  
  15.   
  16. <!-- 配置事务管理器 -->  
  17. <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  18.     <property name="sessionFactory" ref="sessionFactory"></property>  
  19. </bean>  
  20.   
  21. <!-- 第四种配置事务的方式,注解 -->  
  22. <tx:annotation-driven transaction-manager="transactionManager"/>  

注解文件:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. package com.dao;  
  2.   
  3. import org.springframework.orm.hibernate3.HibernateTemplate;  
  4. import org.springframework.transaction.annotation.Propagation;  
  5. import org.springframework.transaction.annotation.Transactional;  
  6.   
  7. import com.entity.User;  
  8.   
  9. @Transactional  
  10. public class UserDaoImpl_BAK extends HibernateTemplate {  
  11.   
  12.     @Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")  
  13.     public void addUser(User user) throws Exception {  
  14.         this.save(user);  
  15.     }  
  16.   
  17.     @Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")  
  18.     public void modifyUser(User user) {  
  19.         this.update(user);  
  20.     }  
  21.   
  22.     @Transactional(propagation=Propagation.REQUIRED,rollbackForClassName="Exception")  
  23.     public void delUser(String username) {  
  24.         this.delete(this.load(User.class, username));  
  25.     }  
  26.   
  27.     @Transactional(readOnly=true)  
  28.     public void selectUser() {  
  29.   
  30.     }  
  31.   
  32. }
类头的@Transactional为默认事务配置,如方法没有自己的事务类型,则按默认事务,如有自己的配置,则按自己的配置。


编程式事务

 
 

程序中手动添加事务:

Connection conn = null;  
UserTransaction tx = null;  
try {  
    tx = getUserTransaction();                       //1.获取事务  
    tx.begin();                                    //2.开启JTA事务  
    conn = getDataSource().getConnection();           //3.获取JDBC  
    //4.声明SQL  
    String sql = "select * from INFORMATION_SCHEMA.SYSTEM_TABLES";  
    PreparedStatement pstmt = conn.prepareStatement(sql);//5.预编译SQL  
    ResultSet rs = pstmt.executeQuery();               //6.执行SQL  
    process(rs);                                   //7.处理结果集  
    closeResultSet(rs);                             //8.释放结果集  
    tx.commit();                                  //7.提交事务  
} catch (Exception e) {  
    tx.rollback();                                 //8.回滚事务  
    throw e;  
} finally {  
   conn.close();                                //关闭连接  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值