开发环境:

OS:windows XP

      Web Server: jakarta-tomcat-5.0.28

      DataBase Server: MS SQL Server 2000 (打了SP3补丁)

      IDE: MyEclipse 6.0.1

测试案例系统结构:

web层<---->Service
层<---->DAO

web层就是Struts2,DAO
使用hibernate -3.3.1.GA-dist.zip,spring
是spring
-framework-2.5.5

数据库表和它一样吧:

student1和Student2,表结构相同:id,name,address.其中id为主键且为自增长型.

student1表中有一条记录:

测试情形一:

web层捕获异常并处理,DAO
层不捕获异常,Service
也不捕获异常.

Service
层接口:

  1. public interface Student1Service {
  2. void addStudent1(Student1 stu);
  3. }
  4. public interface StudentSService {
  5. void addStudent2(Student2 stu) throws SaveException;
  6. }

Service
实现

  1. public void addStudent1(Student1 stu) {
  2. stufDAO.insertStuF(stu);
  3. }
  4. public void addStudent2(Student2 stu) throws SaveException {
  5. String[] aa={"ww","ww","ww"};
  6. for(int i=0;i<5;i++){        //出错
  7. System.out.println(aa[i]);
  8. }
  9. stusDAO.insertStuS(stu);
  10. }

DAO
层接口

  1. public interface StudentFDAO {
  2. void insertStuF(Student1 stu);
  3. }
  4. public interface StudentSDAO {
  5. void insertStuS(Student2 stu);
  6. }

DAO
实现

  1. public void insertStuF(Student1 stu) {
  2. getHibernateTemplate().save (stu);
  3. }
  4. public void insertStuS(Student2 stu) {
  5. getHibernateTemplate().save (stu);
  6. }

Action

  1. public String execute() throws Exception{
  2. Student1 sti=new Student1(stu1Name,stu1Address);
  3. Student2 stu=new Student2(stu1Name,stu1Address);
  4. try{
  5. studentfService.addStudent1(sti);
  6. studentsService.addStudent2(stu);
  7. }catch(DataAccessException  e){
  8. System.out.println(“error”);
  9. return “failer”:
  10. }
  11. return SUCCESS;
  12. }

JSP

  1. <form action="testaction.action" method="POST">
  2. <table>
  3. <tr><td>名:</td><td><input type="text"  value="stu1Name" name="stu1Name"></td></tr>
  4. <tr><td>地址:</td><td><input type="text"  value="stu1Address" name="stu1Address"></td></tr>
  5. <Tr><td></td><td><input type="submit"  value="提交"  style="width:80px"></td></Tr>
  6. </table>
  7. </form>

配置文件

  1. <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  2. <property name="sessionFactory" ref="sessionFactory"/>
  3. </bean>
  4. <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
  5. <property name="transactionManager" ref="transactionManager"/>
  6. <property name="transactionAttributes">
  7. <props>
  8. <prop key="*">PROPAGATION_REQUIRED</prop>
  9. <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
  10. </props>
  11. </property>
  12. </bean>
  13. <!-- 定义BeanNameAutoProxyCreator-->
  14. <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  15. <property name="beanNames">
  16. <list>
  17. <value>st1Service</value>
  18. <value>stsService</value>
  19. </list>
  20. </property>
  21. <property name="interceptorNames">
  22. <list>
  23. <value>transactionInterceptor</value>
  24. </list>
  25. </property>
  26. </bean>

运行程序:启动服务器,并部署.进入index.jsp页面,点击提交

查看数据库: 两个表中都没有新增数据。

小结:如果DAO
层和Service
不捕获异常而在web层捕获异常,web成功捕获异常(抛不抛出都行),spring
事务管理成功!

二、Service
层捕捉异常,DAO
不捕捉异常(下面就简单一点了,直接给结论把)

1.如果,你在Service
捕捉异常而不抛出异常,Action层捕捉不到异常,那么事物处理失败。

2.如果在Service
捕捉异常并且抛出异常,那么,如果抛出的异常是Checked异常(自定义的),不会回滚。也正好验证了Spring
事物里的这段话:默认情况下,事物只会出现运行异常(runtime exception)时回滚,而出现受阻异常(checked exception)时不回滚。

3.如果抛出的异常是RuntimeChecked异常(自定义的),那么事物处理成功。

所以如果你的抛出的异常是CheckException,你配置事物的时候必须加上-Exception参数,指定出现Checked异常时回滚,也就是PROPAGATION_REQUIRED,-Exception。

三、DAO
捕获异常

如果DAO
捕捉异常而不抛出异常,Action层捕捉不到异常,Service
捕获不到异常。

运行程序:启动服务器,并部署.进入index.jsp页面,点击提交

查看数据库:student1表中新曾数据,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层捕获,这样我们就可以手动编码的灵活实现通过业务方法执行的成功和失败来向用户转发不同的页面


其实这到不是因为自定义异常为DataAccessException的子类,而是DataAccessException是
RuntimeException,那么它的子类也是Runtime,所以抛出异常是会回滚的。所以你的自定义异常继承自
RuntimeException也可以。

再发表一些个人看发吧,在Spring
中所有数据库操作异常都转换为DataAccessException这个运行时异常,不过在业务层中也有可能抛出一些其他的运行时异常,那么这时候在一些简单的项目中,我们直接用下面的方式也未尝不可:

Java代码

  1. try{
  2. …….
  3. ………
  4. ……..(可能会有其他运行时异常,并不仅仅是DataAccessException)
  5. }catch(Exception e){
  6. log.error(“error”);
  7. throw new CheckedException(“error”);    //抛出受检查异常
  8. }

然后在Action层捕捉这个受检查异常

Java代码

  1. try{
  2. service.method();
  3. }catch(CheckedException e){
  4. }

这个异常,它是可以被调用者正确处理的。返回相应的提示。当然,如果抛出CheckException,那么Spring
声明式事物的时候就应该加上-Exception参数,前面已经提到。

当然在一些业务逻辑比较复杂,并且要根据复杂的逻辑返回不同的试图的时候,这样整个的try{}catch(){}就不合适了,这时候应该将不正常的事件流转换为运行时异常,并且在方法声明中详细的说明该方法可能会抛出的unChekced异常。由调用者自己去决定是否捕获unChecked异常

,返回相应的视图。

总结:

1.一般DAO
中不捕捉异常也不抛出异常

2.至于Service
层和Action层,是在service
层抛出CheckException然后由action捕捉,还是在service
中全部采用unCheckException,然后在action中有选择的捕捉或者都不捕捉就要看你自己的选择了, 个人认为逻辑比较简单的可以选择前者,比较复杂就选择后者。

3.禁忌捕捉异常而不做任何处理(如果是dao
层或者service
层,最好抛出),不然很有可能造成事务处理失败。

Spring事务处理探究的更多相关文章

  1. Spring事务处理

    事务(Transaction)是并发控制的单位,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位. 数据库向用户提供保存当前程序状态的方法,叫事务提交(commit): ...

  2. java 之DelayQueue,TaskDelayed,handlerFactory,dataChange消息配置.收发等.java spring事务处理TransactionTemplate

    java 之DelayQueue,TaskDelayed,handlerFactory,dataChange消息配置.收发等.java spring事务处理TransactionTemplate等. ...

  3. 【spring 注解驱动开发】spring事务处理原理

    尚学堂spring 注解驱动开发学习笔记之 - 事务处理 事务处理 1.事务处理实现 实现步骤: * 声明式事务: * * 环境搭建: * 1.导入相关依赖 * 数据源.数据库驱动.Spring-jd ...

  4. Spring Security探究之路之开始

    前言 在Spring Security介绍中,我们分析到了根据请求获取匹配的SecurityFilterChain,这个类中包含了一组Filter 接下来我们从这些Filter开始探究之旅 Sprin ...

  5. Spring 事务处理

    Spring 默认执行事务回滚:当开启事务的类中对数据库的操作的异常没有任何处理时,才会主动触发事务回滚. 而很多时候业务都需要对抛出的异常进行处理,所以如果try,catch了操作数据库的方法,事务 ...

  6. Spring Boot探究之旅--启动分析

    刚接触SpringBoot,感觉挺方便的,不用配置那么多乱七八糟的配置,很方便!酒饱思淫欲,得陇望蜀一下,看看SpringBoot到底怎么做到这么方便的. 首先呢,先来看个SpringBoot的hel ...

  7. 【转】Java异常总结和Spring事务处理异常机制浅析

    异常的概念和Java异常体系结构 异常是程序运行过程中出现的错误.本文主要讲授的是Java语言的异常处理.Java语言的异常处理框架,是Java语言健壮性的一个重要体现. Thorwable类所有异常 ...

  8. Spring事务处理时自我调用的解决方案 嵌套AOP

    开涛的解决方案1 http://jinnianshilongnian.iteye.com/blog/1487235 AopContext.currentProxy() 原理 http://books. ...

  9. Java异常总结和Spring事务处理异常机制浅析

    异常的概念和Java异常体系结构 异常是程序运行过程中出现的错误.本文主要讲授的是Java语言的异常处理.Java语言的异常处理框架,是Java语言健壮性的一个重要体现. Thorwable类所有异常 ...

随机推荐

  1. 一步一步学习IdentityServer4 (6) Connect-OpenId Cookies SignIn SignOut 那些事

    先来看下下面的配置: JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); services.AddAuthentication( o ...

  2. python 库资源大全

    偶然的机会翻到这篇文章,很全面,来源:  Python 资源大全中文版       哪些 Python 库让你相见恨晚? 环境管理 管理 Python 版本和环境的工具 p:非常简单的交互式 pyth ...

  3. 程序设计实习MOOC / 程序设计与算法(三)第一周测验

    作业题: 7. 填空(2分)简单的swap 通过码是 ( 请参考公告中的“关于编程作业的说明”完成编程作业(请注意,编程题都要求提交通过码,在openjudge上提交了程序并且通过以后,就可以下载到通 ...

  4. 【51nod】1559 车和矩形

    题解 离线读入,我们发现一个矩形能被保护,矩形内部所有列上必定有一辆车,或者所有行上必定有一辆车 分两次进行处理 第一次按照横坐标把车加进去,然后查询最大横坐标在这个位置的矩形,纵坐标区间里的车出现位 ...

  5. codeforces 603 A

    题目大意:给你一个0,1串, 你可以反转一段连续的区间,问你最长的合法子串是多长, 合法字串相邻的两个不能相同. 思路:dp[ i ][ k ][ j ] 表示到第 i 个字符, 处于k这种状态, k ...

  6. Ubuntu16.04下Kylin的安装与配置

    一.系统环境 kylin的安装配置并不像官方文档中描述的那样简单,复杂的原因在于hadoop,hive,hbase,kylin的版本一定要兼容,不然就会出现各种奇怪的错误.以下各软件版本可以成功运行k ...

  7. 【转】关于Jmeter3.0,你必须要知道的5点变化

    2016.5.18日,Apache 发布了jmeter 3.0版本,本人第一时间上去查看并下载使用了,然后群里或同事都会问有什么样变化呢?正好在网上看到一遍关于3.0的文章,但是是英文的.这里翻译一下 ...

  8. Expression表达式树 案例

    1,Expression.Invoke //运用委托或Lambda表达式 System.Linq.Expressions.Expression<Func<; System.Linq.Exp ...

  9. codevs 1365 浴火银河星际跳跃

    1365 浴火银河星际跳跃 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 小 K 又在玩浴火银河了...不过这次他的目的不是跑运输 ...

  10. hdu 3308 线段树

    题目大意:给n个数,两种操作1:U  a b   更新第a个为b (从0开始)2: Q    a ,b  查询 a,b之间LCIS(最长连续递增子序列)的长度. Sample Input110 107 ...