Spring事务配置的几种方式

 Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。

    DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

    具体如下图:

Spring事务配置 (2)

    根据代理机制的不同,总结了五种Spring事务的配置方式,配置文件如下:

    第一种方式:每个Bean都有一个代理

<? 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:context
="http://www.springframework.org/schema/context"
    xmlns:aop
="http://www.springframework.org/schema/aop"
    xsi:schemaLocation ="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
>

    
< bean  id ="sessionFactory"   
            class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >   
        
< property  name ="configLocation"  value ="classpath:hibernate.cfg.xml"   />   
        
< property  name ="configurationClass"  value ="org.hibernate.cfg.AnnotationConfiguration"   />
    
</ bean >   

    
<!--  定义事务管理器(声明式的事务)  -->   
    
< bean  id ="transactionManager"
        class
="org.springframework.orm.hibernate3.HibernateTransactionManager" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >
    
    
<!--  配置DAO  -->
    
< bean  id ="userDaoTarget"  class ="com.bluesky.spring.dao.UserDaoImpl" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >
    
    
< bean  id ="userDao"   
        class
="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >   
           
<!--  配置事务管理器  -->   
           
< property  name ="transactionManager"  ref ="transactionManager"   />      
        
< property  name ="target"  ref ="userDaoTarget"   />   
         
< property  name ="proxyInterfaces"  value ="com.bluesky.spring.dao.GeneratorDao"   />
        
<!--  配置事务属性  -->   
        
< property  name ="transactionAttributes" >   
            
< props >   
                
< prop  key ="*" > PROPAGATION_REQUIRED </ prop >
            
</ props >   
        
</ property >   
    
</ bean >   
</ beans >

    第二种方式:所有Bean共享一个代理基类

<? 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:context
="http://www.springframework.org/schema/context"
    xmlns:aop
="http://www.springframework.org/schema/aop"
    xsi:schemaLocation
="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
>

    
< bean  id ="sessionFactory"   
            class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >   
        
< property  name ="configLocation"  value ="classpath:hibernate.cfg.xml"   />   
        
< property  name ="configurationClass"  value ="org.hibernate.cfg.AnnotationConfiguration"   />
    
</ bean >   

    
<!--  定义事务管理器(声明式的事务)  -->   
    
< bean  id ="transactionManager"
        class
="org.springframework.orm.hibernate3.HibernateTransactionManager" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >
    
    
< bean  id ="transactionBase"   
            class
="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"   
            lazy-init
="true"  abstract ="true" >   
        
<!--  配置事务管理器  -->   
        
< property  name ="transactionManager"  ref ="transactionManager"   />   
        
<!--  配置事务属性  -->   
        
< property  name ="transactionAttributes" >   
            
< props >   
                
< prop  key ="*" > PROPAGATION_REQUIRED </ prop >   
            
</ props >   
        
</ property >   
    
</ bean >     
   
    
<!--  配置DAO  -->
    
< bean  id ="userDaoTarget"  class ="com.bluesky.spring.dao.UserDaoImpl" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >
    
    
< bean  id ="userDao"  parent ="transactionBase"   >   
        
< property  name ="target"  ref ="userDaoTarget"   />    
    
</ bean >
</ beans >

第三种方式:使用拦截器

<? 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:context
="http://www.springframework.org/schema/context"
    xmlns:aop
="http://www.springframework.org/schema/aop"
    xsi:schemaLocation ="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
>

    
< bean  id ="sessionFactory"   
            class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >   
        
< property  name ="configLocation"  value ="classpath:hibernate.cfg.xml"   />   
        
< property  name ="configurationClass"  value ="org.hibernate.cfg.AnnotationConfiguration"   />
    
</ bean >   

    
<!--  定义事务管理器(声明式的事务)  -->   
    
< bean  id ="transactionManager"
        class
="org.springframework.orm.hibernate3.HibernateTransactionManager" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >  
   
    
< bean  id ="transactionInterceptor"   
        class
="org.springframework.transaction.interceptor.TransactionInterceptor" >   
        
< property  name ="transactionManager"  ref ="transactionManager"   />   
        
<!--  配置事务属性  -->   
        
< property  name ="transactionAttributes" >   
            
< props >   
                
< prop  key ="*" > PROPAGATION_REQUIRED </ prop >   
            
</ props >   
        
</ property >   
    
</ bean >
      
    
< bean  class ="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >   
        
< property  name ="beanNames" >   
            
< list >   
                
< value > *Dao </ value >
             </ list >   
        
</ property >   
        
< property  name ="interceptorNames" >   
            
< list >   
                
< value > transactionInterceptor </ value >   
            
</ list >   
        
</ property >   
    
</ bean >   
  
    
<!--  配置DAO  -->
    
< bean  id ="userDao"  class ="com.bluesky.spring.dao.UserDaoImpl" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >
</ beans >

第四种方式:使用tx标签配置的拦截器

<? 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:context
="http://www.springframework.org/schema/context"
    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.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
>

    
< context:annotation-config  />
    
< context:component-scan  base-package ="com.bluesky"   />

    
< bean  id ="sessionFactory"   
            class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >   
        
< property  name ="configLocation"  value ="classpath:hibernate.cfg.xml"   />   
        
< property  name ="configurationClass"  value ="org.hibernate.cfg.AnnotationConfiguration"   />
    
</ bean >   

    
<!--  定义事务管理器(声明式的事务)  -->   
    
< bean  id ="transactionManager"
        class
="org.springframework.orm.hibernate3.HibernateTransactionManager" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >

    
< tx:advice  id ="txAdvice"  transaction-manager ="transactionManager" >
        
< tx:attributes >
            
< tx:method  name ="*"  propagation ="REQUIRED"   />
        
</ tx:attributes >
    
</ tx:advice >
    
    
< aop:config >
        
< aop:pointcut  id ="interceptorPointCuts"
            expression
="execution(* com.bluesky.spring.dao.*.*(..))"   />
        
< aop:advisor  advice-ref ="txAdvice"
            pointcut-ref
="interceptorPointCuts"   />         
    
</ aop:config >       
</ beans >

第五种方式:全注解

<? 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:context
="http://www.springframework.org/schema/context"
    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.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
>

    
< context:annotation-config  />
    
< context:component-scan  base-package ="com.bluesky"   />

    
< tx:annotation-driven  transaction-manager ="transactionManager" />

    
< bean  id ="sessionFactory"   
            class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >   
        
< property  name ="configLocation"  value ="classpath:hibernate.cfg.xml"   />   
        
< property  name ="configurationClass"  value ="org.hibernate.cfg.AnnotationConfiguration"   />
    
</ bean >   

    
<!--  定义事务管理器(声明式的事务)  -->   
    
< bean  id ="transactionManager"
        class
="org.springframework.orm.hibernate3.HibernateTransactionManager" >
        
< property  name ="sessionFactory"  ref ="sessionFactory"   />
    
</ bean >
    
</ beans >

此时在DAO上需加上@Transactional注解,如下:

package  com.bluesky.spring.dao;

import  java.util.List;

import  org.hibernate.SessionFactory;
import  org.springframework.beans.factory.annotation.Autowired;
import  org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import  org.springframework.stereotype.Component;

import  com.bluesky.spring.domain.User;

@Transactional
@Component(
" userDao " )
public   class  UserDaoImpl  extends  HibernateDaoSupport  implements  UserDao {

    
public  List < User >  listUsers() {
        
return   this .getSession().createQuery( " from User " ).list();
    }
    
    
}






关于spring事务管理以及异常处理的帖子,本论坛争论颇多,各有各的测试代码,也各有各的测试结果,不知道是spring版本的不同还是各测试的例子的不同而导致测试结果出现差异.本人也很想弄清楚spring是如何对Service进行事务管理的,并且还去看了一下spring框架关于事务管理几个相关类的源码,可惜由于本人功力有限,只看懂了皮毛.既然源代码看不懂,那么只有运用例子进行测试,虽然笨了点,不过管是白猫还是黑猫,能捉老鼠就是好猫.:)为引起不必要的争论,本帖子只针对本案例的测试结果进行小结,并保证此测试代码在本人的运行环境绝对正确. 

开发环境: 
OS:windows 2003 Server 
Web Server: jakarta-tomcat-5.0.28 
DataBase Server: MS SQL Server 2000 
IDE:  Eclipse 3.2.0 

测试案例系统结构: 
web层<---->Service层<---->DAO层 

web层使用struts 1.1,DAO使用的spring的JDBC,spring版本1.2 

数据库中有两张表: 
student1和Student2,表结构相同:id,name,address.其中id为主键且为自增长型. 
student1表中有一条记录: 
Java代码   收藏代码
  1. id  name       address   
  2. 1   xiaoming    wuhan   
     
student2表中记录为空 

测试情形一: 
web层捕获异常并处理,DAO层不捕获异常,Service也不捕获异常. 

Service层接口: 
Java代码   收藏代码
  1. public interface StudentManagerService {   
  2.      
  3.     public void  bus_method();   
  4. }   

DAO层接口 
Java代码   收藏代码
  1. public interface StudentDAO {   
  2.      
  3.     public void  deleteStudent1();   
  4.     public void  insertStudent2();   
  5. }   

StudentDAO接口的实现: 
Java代码   收藏代码
  1. public class StudentDAOImp extends JdbcDaoSupport implements StudentDAO{   
  2.      //删除student1表中的id=1的记录   
  3.      public void  deleteStudent1(){   
  4.      JdbcTemplate jt=this.getJdbcTemplate();   
  5.      jt.update("delete from student1 where id=1");        
  6.    }   
  7.         
  8.      //将student1表中删除的记录插入到student2中,但是此方法实现有错,因为   
  9.    //id字段设置为自增长的,所以在插入记录时我们不能指定值   
  10.       public void  insertStudent2(){   
  11.        JdbcTemplate jt=this.getJdbcTemplate();   
  12.             String arg[]=new String[3];   
  13.        arg[0]="1";   
  14.             arg[1]="xiaoming";   
  15.        arg[2]="wuhan";   
  16.             jt.update("insert student2(id,name,address) values(?,?,?)",arg);   
  17.      }   
  18.    
  19. }    

StudentManagerService 接口的实现: 
Java代码   收藏代码
  1. public class StudentManagerServiceImp implements StudentManagerService{   
  2.   private StudentDAO  stdDAO;   
  3.     
  4.   public void setStdDAO(StudentDAO   stdDAO){   
  5.      this.stdDAO=stdDAO;   
  6.   }   
  7.       
  8.   //此方法为事务型的:删除student1中的记录成功且插入student2的记录也成功,   
  9.  //如果insertStudent2()方法执行失败,那么deleteStudent1()方法也应该会失败   
  10.   public void  bus_method(){   
  11.     this.stdDAO.deleteStudent1();   
  12.     this.stdDAO.insertStudent2();   
  13.   }   
  14.      
  15. }    

web层: 
三个jsp,一个action: 
index.jsp ==>首页面.上面仅仅有一个超链接<a herf="test.do">执行</a> 
chenggong.jsp ==>Service执行成功后转向的JSP页面 
shibai.jsp ====>Service执行失败后转向的JSP页面 

action实现: 
Java代码   收藏代码
  1. public class StudentManagerAction  extends  Action{   
  2.    
  3.      public ActionForward execute(ActionMapping mapping, ActionForm form,   
  4.     HttpServletRequest request, HttpServletResponse response) {   
  5.          try{   
  6.              WebApplicationContext appContext=WebApplicationContextUtils.    
  7.                   getWebApplicationContext(this.getServlet().getServletContext());   
  8.         StudentManagerService stdm=(StudentManagerService)appContext.   
  9.                                         getBean("stdServiceManager");   
  10.             stdm.bus_method();   
  11.             return mapping.findForward("chenggong");   
  12.      }   
  13.      catch(DataAccessException e){   
  14.         System.err.println("action execute service exception!");   
  15.         return mapping.findForward("shibai");   
  16.       }   
  17.    
  18.     }   
  19. }   

配置文件: 
web.xml
 
Java代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">   
  3.   <context-param>   
  4.     <param-name>log4jConfigLocation</param-name>   
  5.     <param-value>/WEB-INF/log4j.properties</param-value>   
  6.   </context-param>   
  7.   <context-param>   
  8.     <param-name>contextConfigLocation</param-name>   
  9.     <param-value>/WEB-INF/applicationContext.xml</param-value>   
  10.   </context-param>   
  11.   <listener>   
  12.     <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>   
  13.   </listener>   
  14.   <listener>   
  15.     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>   
  16.   </listener>   
  17.   <servlet>   
  18.     <servlet-name>action</servlet-name>   
  19.     <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>   
  20.     <init-param>   
  21.       <param-name>config</param-name>   
  22.       <param-value>/WEB-INF/struts-config.xml</param-value>   
  23.     </init-param>   
  24.     <init-param>   
  25.       <param-name>debug</param-name>   
  26.       <param-value>3</param-value>   
  27.     </init-param>   
  28.     <init-param>   
  29.       <param-name>detail</param-name>   
  30.       <param-value>3</param-value>   
  31.     </init-param>   
  32.     <load-on-startup>0</load-on-startup>   
  33.   </servlet>   
  34.   <servlet-mapping>   
  35.     <servlet-name>action</servlet-name>   
  36.     <url-pattern>*.do</url-pattern>   
  37.   </servlet-mapping>   
  38. </web-app>   

sturts-config.xml 
Java代码   收藏代码
  1. <struts-config>   
  2.    <action-mappings >   
  3.      <action  input="/index.jsp"  path="/test"  type="test.StudentManagerAction   >   
  4.        <forward name="chenggong" path="/chenggong.jsp" />   
  5.        <forward name="shibai" path="/shibai.jsp" />   
  6.      </action>   
  7.    </action-mappings>   
  8.    <message-resources parameter="test.ApplicationResources" />   
  9.  </struts-config>   

applicationContext.xml 
Java代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">   
  3. <beans>   
  4.     <bean id="dataSource"   
  5.       class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >   
  6.       <property name="driverClassName" value="com.microsoft.jdbc.sqlserver.SQLServerDriver"></property>   
  7.       <property name="url" value="jdbc:microsoft:sqlserver://127.0.0.1:1433;databasename=test"></property>   
  8.        <property name="username" value="sa"></property>   
  9.        <property name="password" value="sa"></property>   
  10.     </bean>   
  11.        
  12.      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">   
  13.         <property name="dataSource" ref="dataSource"/>   
  14.      </bean>   
  15.            
  16.     <bean id="baseTxProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"  lazy-init="true">   
  17.         <property name="transactionManager">   
  18.         <ref bean="transactionManager" />   
  19.          </property>   
  20.          <property name="transactionAttributes">   
  21.          <props>   
  22.              <prop key="*">PROPAGATION_REQUIRED</prop>   
  23.         </props>   
  24.          </property>   
  25.     </bean>   
  26.    
  27.     <bean id="stdServiceManager"  parent="baseTxProxy" >   
  28.         <property name="target">   
  29.              <bean class="test.StudentManagerServiceImp">       
  30.                        <property name="stdDAO">   
  31.                       <ref bean="stdDAO"/>   
  32.                        </property>       
  33.                   </bean>    
  34.         </property>    
  35.     </bean>   
  36.    
  37.     <bean id="stdDAO" class="test.StudentDAOImp">   
  38.        <property name="dataSource" ref="dataSource"/>   
  39.     </bean>   
  40. </beans>   

运行程序:启动服务器,并部署.进入index.jsp页面,点击"执行"超链接"---->页面跳向shibai.jsp 
查看控制台:打印有:action execute service exception! 
查看数据库: student1表中的[1 xiaoming  wuhan] 记录仍然存在,student2表仍然为空. 
小结:如果DAO层和Service不捕获异常而在web层捕获异常,web成功捕获异常,spring事务管理成功! 

测试情形二: 
web层捕获异常并处理,Service捕获异常并处理,DAO层不捕获异常. 

修改StudentManagerServiceImp类 
Java代码   收藏代码
  1. public class StudentManagerServiceImp implements StudentManagerService{   
  2.   private StudentDAO  stdDAO;   
  3.    
  4.   public void setStdDAO(StudentDAO   stdDAO){   
  5.      this.stdDAO=stdDAO;   
  6.   }   
  7.       
  8.   //此方法为事务型的,删除student1中的记录成功且插入student2的记录也成功   
  9.  //如果insertStudent2()方法执行失败,那么deleteStudent1()也应该会失败   
  10.   public void  bus_method(){   
  11.    try{   
  12.       this.stdDAO.deleteStudent1();   
  13.       this.stdDAO.insertStudent2();   
  14.    }   
  15.    catch(DataAccessException de)   
  16.        System.err.println("service execute exception!");   
  17.     }   
  18.   }   
  19.      
  20. }   


运行程序:启动服务器,并部署.进入index.jsp页面,点击"执行"超链接"---->页面跳向chenggong.jsp 
查看控制台:打印有:service execute exception! 
查看数据库: student1表中的[1  xiaoming  wuhan] 记录不存在,student2表仍然为空. 
小结:如果Service捕获异常并处理而不向外抛出,web层捕获不到异常,spring事务管理失败! 

测试情形(还原表中的数据)三: 
web层捕获异常,Service捕获异常,DAO层也捕获异常. 
修改StudentDAOImp类代码 
Java代码   收藏代码
  1. public class StudentDAOImp extends JdbcDaoSupport implements StudentDAO{   
  2.      //删除student1表中的id=1的记录   
  3.      public void  deleteStudent1(){   
  4.         try{   
  5.      JdbcTemplate jt=this.getJdbcTemplate();   
  6.      jt.update("delete from student1 where id=1");   
  7.        }   
  8.        catch(DataAccessException e){   
  9.          System.err.println("dao deleteStudent1 execute exception!");   
  10.        }        
  11.    }   
  12.         
  13.      //将student1表中删除的记录插入到student2中,但是此方法实现有错,因为   
  14.    //id字段设置为自增长的,所以在插入记录时我们不能指定值   
  15.       public void  insertStudent2(){   
  16.           try{   
  17.        JdbcTemplate jt=this.getJdbcTemplate();   
  18.             String arg[]=new String[3];   
  19.        arg[0]="1";   
  20.             arg[1]="xiaoming";   
  21.        arg[2]="wuhan";   
  22.             jt.update("insert student2(id,name,address) values(?,?,?)",arg);   
  23.          }   
  24.          catch(DataAccessException  e){   
  25.             System.err.println("dao insertStudent2  execute exception!");   
  26.    
  27.          }   
  28.      }   
  29.    
  30. }    

运行程序:启动服务器,并部署.进入index.jsp页面,点击"执行"超链接"---->页面跳向chenggong.jsp 
查看控制台:打印有:dao insertStudent2  execute exception! 
查看数据库: student1表中的 1,xiaoming,wuhan 记录不存在,student2表仍然为空. 
小结如果DAO的每一个方法自己捕获异常并处理而不向外抛出,Service层捕获不到异常,Web层同样捕获不到异常,spring事务管理失败! 

测试情形四: 
还原数据库中的数据
 
还原StudentDAOImp类中的方法为测试情形一中的实现web层捕获异常Service抛出的自定义异常StudentManagerException Service捕获DataAccessException并抛出StudentManagerException,StudentManagerException为DataAccessException的子类DAO层不捕获异常 

修改StudentManagerServiceImp类的实现: 
Java代码   收藏代码
  1. public class StudentManagerServiceImp implements StudentManagerService{   
  2.   private StudentDAO  stdDAO;   
  3.     
  4.   public void setStdDAO(StudentDAO   stdDAO){   
  5.      this.stdDAO=stdDAO;   
  6.   }   
  7.       
  8.   //此方法为事务型的,删除student1中的记录成功且插入student2的记录也成功   
  9. //如果insertStudent2()方法执行失败,那么deleteStudent1()也应该会失败   
  10.   public void  bus_method() throws StudentManagerException{   
  11.    try{   
  12.       this.stdDAO.deleteStudent1();   
  13.       this.stdDAO.insertStudent2();   
  14.    }   
  15.    catch(DataAccessException de)   
  16.        System.err.println("service execute exception!");   
  17.      throw new StudentManagerException();//StudentManagerException类继承DataAcce                            
  18.        //ssException异常   
  19.     }   
  20.   }   
  21. }   

修改StudentManagerAction 
Java代码   收藏代码
  1. public class StudentManagerAction  extends  Action{   
  2.    
  3.      public ActionForward execute(ActionMapping mapping, ActionForm form,   
  4.     HttpServletRequest request, HttpServletResponse response) {   
  5.          try{   
  6.              WebApplicationContext appContext=WebApplicationContextUtils.    
  7.                   getWebApplicationContext(this.getServlet().getServletContext());   
  8.         StudentManagerService stdm=(StudentManagerService)appContext.   
  9.                                         getBean("stdServiceManager");   
  10.             stdm.bus_method();   
  11.             return mapping.findForward("chenggong");   
  12.      }   
  13.      catch(StudentManagerException e){   
  14.         System.err.println("action execute service exception!");   
  15.         return mapping.findForward("shibai");   
  16.       }   
  17.    
  18.     }   
  19. }   

运行程序:启动服务器,并部署.进入index.jsp页面,点击"执行"超链接"---->页面跳向shibai.jsp 
查看控制台:打印有:service execute exception! action execute service exception! 
查看数据库:student1表中的 [1,xiaoming,wuhan] 记录仍然存在,student2表仍然为空. 
小结如果DAO的每一个方法不捕获异常,Service层捕获DataAccessException异常并抛出自己定义异常(自定义异常为DataAccessException的子类),Web层可以捕获到异常,spring事务管理成功! 

结合源码总结: 
1.spring在进行声明时事务管理时,通过捕获Service层方法的DataAccessException来提交和回滚事务的,而Service层方法的DataAccessException又是来自调用DAO层方法所产生的异常. 

2.我们一般在写DAO层代码时,如果继承JdbcDaoSupport 类,并使用此类所实现的JdbcTemplate来执行数据库操作,此类会自动把低层的SQLException转化成 DataAccessException以及DataAccessException 
的子类. 

3.一般在Service层我们可以自己捕获DAO方法所产成的DataAccessException,然后再抛出一个业务方法有意义的异常 (ps:此异常最好继承DataAccessException),然后在Web层捕获,这样我们就可以手动编码的灵活实现通过业务方法执行的成功和失败来向用户转发不同的页面






************************************************ ************************************************************************************************
可用:
<?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">

    <!-- 配置SessionFactory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
        </property>
    </bean>

    <!-- 配置事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref bean="sessionFactory" />
        </property>
    </bean>

    <!-- 哪些类哪些方法使用事务 -->
    <aop:config>
        <aop:pointcut id="allServiceMethod"
            expression="execution(* com.archermind.service.*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethod" />
    </aop:config>

    <!-- 事务的传播特性 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="del*" propagation="REQUIRED" />
            <tx:method name="modify*" propagation="REQUIRED" />
            <tx:method name="*" propagation="REQUIRED" read-only="true" />
        </tx:attributes>
    </tx:advice>
    <!-- aaa -->
    <!-- ccc -->
    <!-- 666 -->

</beans>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值