- 浏览: 3100656 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (372)
- diy (4)
- linux (19)
- 杂项 (30)
- Swing (21)
- Java2D (21)
- Java3D (5)
- JavaIO (9)
- Java通讯 (5)
- Java设计模式 (3)
- Java多媒体 (0)
- Java算法 (7)
- Spring&EJB (29)
- Javaoffice (4)
- web前端 (23)
- javascript (1)
- php基础 (1)
- eclipse (3)
- 网站相关 (3)
- Apache (4)
- seo (12)
- db (28)
- server (3)
- api (4)
- 异常 (12)
- 计算机网络词汇表 (3)
- 随想录 (52)
- 收藏 (17)
- 犹太人的智慧 (3)
- 多线程 (1)
- jfreechart (7)
- Test (1)
- SorLib (30)
- ruby on rails (1)
最新评论
-
houyutao:
二三四都是错的空字符串也被匹配,*应该改成+
Java中判断字符串是否为数字的五种方法 -
mingyun:
但是 java.util.ArrayList 实现了 remo ...
java.lang.UnsupportedOperationException 解决方案 -
mingyun:
1.因为 Arrays.asList 返回的是 Arrays内 ...
java.lang.UnsupportedOperationException 解决方案 -
leolu007:
用java8新特性String testStr = " ...
java.lang.UnsupportedOperationException 解决方案 -
zhaohuaxishiwzw:
我之前所在的项目就是日本一家证券公司的项目。完全使用的是j2e ...
抛弃EJB(EJB2.0,EJB3.0,EJB4.0)
关于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表中有一条记录:
student2表中记录为空
测试情形一:
web层捕获异常并处理,DAO层不捕获异常,Service也不捕获异常.
Service层接口:
DAO层接口
StudentDAO接口的实现:
StudentManagerService 接口的实现:
web层:
三个jsp,一个action:
index.jsp ==>首页面.上面仅仅有一个超链接<a herf="test.do">执行</a>
chenggong.jsp ==>Service执行成功后转向的JSP页面
shibai.jsp ====>Service执行失败后转向的JSP页面
action实现:
配置文件:
web.xml
sturts-config.xml
applicationContext.xml
运行程序:启动服务器,并部署.进入index.jsp页面,点击"执行"超链接"---->页面跳向shibai.jsp
查看控制台:打印有:action execute service exception!
查看数据库: student1表中的[1 xiaoming wuhan] 记录仍然存在,student2表仍然为空.
小结:如果DAO层和Service不捕获异常而在web层捕获异常,web成功捕获异常,spring事务管理成功!
测试情形二:
web层捕获异常并处理,Service捕获异常并处理,DAO层不捕获异常.
修改StudentManagerServiceImp类
运行程序:启动服务器,并部署.进入index.jsp页面,点击"执行"超链接"---->页面跳向chenggong.jsp
查看控制台:打印有:service execute exception!
查看数据库: student1表中的[1 xiaoming wuhan] 记录不存在,student2表仍然为空.
小结:如果Service捕获异常并处理而不向外抛出,web层捕获不到异常,spring事务管理失败!
测试情形(还原表中的数据)三:
web层捕获异常,Service捕获异常,DAO层也捕获异常.
修改StudentDAOImp类代码
运行程序:启动服务器,并部署.进入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类的实现:
修改StudentManagerAction
运行程序:启动服务器,并部署.进入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层捕获,这样我们就可以手动编码的灵活实现通过业务方法执行的成功和失败来向用户转发不同的页面.
开发环境:
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表中有一条记录:
id name address 1 xiaoming wuhan
student2表中记录为空
测试情形一:
web层捕获异常并处理,DAO层不捕获异常,Service也不捕获异常.
Service层接口:
public interface StudentManagerService { public void bus_method(); }
DAO层接口
public interface StudentDAO { public void deleteStudent1(); public void insertStudent2(); }
StudentDAO接口的实现:
public class StudentDAOImp extends JdbcDaoSupport implements StudentDAO{ //删除student1表中的id=1的记录 public void deleteStudent1(){ JdbcTemplate jt=this.getJdbcTemplate(); jt.update("delete from student1 where id=1"); } //将student1表中删除的记录插入到student2中,但是此方法实现有错,因为 //id字段设置为自增长的,所以在插入记录时我们不能指定值 public void insertStudent2(){ JdbcTemplate jt=this.getJdbcTemplate(); String arg[]=new String[3]; arg[0]="1"; arg[1]="xiaoming"; arg[2]="wuhan"; jt.update("insert student2(id,name,address) values(?,?,?)",arg); } }
StudentManagerService 接口的实现:
public class StudentManagerServiceImp implements StudentManagerService{ private StudentDAO stdDAO; public void setStdDAO(StudentDAO stdDAO){ this.stdDAO=stdDAO; } //此方法为事务型的:删除student1中的记录成功且插入student2的记录也成功, //如果insertStudent2()方法执行失败,那么deleteStudent1()方法也应该会失败 public void bus_method(){ this.stdDAO.deleteStudent1(); this.stdDAO.insertStudent2(); } }
web层:
三个jsp,一个action:
index.jsp ==>首页面.上面仅仅有一个超链接<a herf="test.do">执行</a>
chenggong.jsp ==>Service执行成功后转向的JSP页面
shibai.jsp ====>Service执行失败后转向的JSP页面
action实现:
public class StudentManagerAction extends Action{ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { try{ WebApplicationContext appContext=WebApplicationContextUtils. getWebApplicationContext(this.getServlet().getServletContext()); StudentManagerService stdm=(StudentManagerService)appContext. getBean("stdServiceManager"); stdm.bus_method(); return mapping.findForward("chenggong"); } catch(DataAccessException e){ System.err.println("action execute service exception!"); return mapping.findForward("shibai"); } } }
配置文件:
web.xml
<?xml version="1.0" encoding="UTF-8"?> <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"> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>/WEB-INF/log4j.properties</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>3</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>3</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>
sturts-config.xml
<struts-config> <action-mappings > <action input="/index.jsp" path="/test" type="test.StudentManagerAction > <forward name="chenggong" path="/chenggong.jsp" /> <forward name="shibai" path="/shibai.jsp" /> </action> </action-mappings> <message-resources parameter="test.ApplicationResources" /> </struts-config>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" > <property name="driverClassName" value="com.microsoft.jdbc.sqlserver.SQLServerDriver"></property> <property name="url" value="jdbc:microsoft:sqlserver://127.0.0.1:1433;databasename=test"></property> <property name="username" value="sa"></property> <property name="password" value="sa"></property> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="baseTxProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> <bean id="stdServiceManager" parent="baseTxProxy" > <property name="target"> <bean class="test.StudentManagerServiceImp"> <property name="stdDAO"> <ref bean="stdDAO"/> </property> </bean> </property> </bean> <bean id="stdDAO" class="test.StudentDAOImp"> <property name="dataSource" ref="dataSource"/> </bean> </beans>
运行程序:启动服务器,并部署.进入index.jsp页面,点击"执行"超链接"---->页面跳向shibai.jsp
查看控制台:打印有:action execute service exception!
查看数据库: student1表中的[1 xiaoming wuhan] 记录仍然存在,student2表仍然为空.
小结:如果DAO层和Service不捕获异常而在web层捕获异常,web成功捕获异常,spring事务管理成功!
测试情形二:
web层捕获异常并处理,Service捕获异常并处理,DAO层不捕获异常.
修改StudentManagerServiceImp类
public class StudentManagerServiceImp implements StudentManagerService{ private StudentDAO stdDAO; public void setStdDAO(StudentDAO stdDAO){ this.stdDAO=stdDAO; } //此方法为事务型的,删除student1中的记录成功且插入student2的记录也成功 //如果insertStudent2()方法执行失败,那么deleteStudent1()也应该会失败 public void bus_method(){ try{ this.stdDAO.deleteStudent1(); this.stdDAO.insertStudent2(); } catch(DataAccessException de) System.err.println("service execute exception!"); } } }
运行程序:启动服务器,并部署.进入index.jsp页面,点击"执行"超链接"---->页面跳向chenggong.jsp
查看控制台:打印有:service execute exception!
查看数据库: student1表中的[1 xiaoming wuhan] 记录不存在,student2表仍然为空.
小结:如果Service捕获异常并处理而不向外抛出,web层捕获不到异常,spring事务管理失败!
测试情形(还原表中的数据)三:
web层捕获异常,Service捕获异常,DAO层也捕获异常.
修改StudentDAOImp类代码
public class StudentDAOImp extends JdbcDaoSupport implements StudentDAO{ //删除student1表中的id=1的记录 public void deleteStudent1(){ try{ JdbcTemplate jt=this.getJdbcTemplate(); jt.update("delete from student1 where id=1"); } catch(DataAccessException e){ System.err.println("dao deleteStudent1 execute exception!"); } } //将student1表中删除的记录插入到student2中,但是此方法实现有错,因为 //id字段设置为自增长的,所以在插入记录时我们不能指定值 public void insertStudent2(){ try{ JdbcTemplate jt=this.getJdbcTemplate(); String arg[]=new String[3]; arg[0]="1"; arg[1]="xiaoming"; arg[2]="wuhan"; jt.update("insert student2(id,name,address) values(?,?,?)",arg); } catch(DataAccessException e){ System.err.println("dao insertStudent2 execute exception!"); } } }
运行程序:启动服务器,并部署.进入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类的实现:
public class StudentManagerServiceImp implements StudentManagerService{ private StudentDAO stdDAO; public void setStdDAO(StudentDAO stdDAO){ this.stdDAO=stdDAO; } //此方法为事务型的,删除student1中的记录成功且插入student2的记录也成功 //如果insertStudent2()方法执行失败,那么deleteStudent1()也应该会失败 public void bus_method() throws StudentManagerException{ try{ this.stdDAO.deleteStudent1(); this.stdDAO.insertStudent2(); } catch(DataAccessException de) System.err.println("service execute exception!"); throw new StudentManagerException();//StudentManagerException类继承DataAcce //ssException异常 } } }
修改StudentManagerAction
public class StudentManagerAction extends Action{ public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { try{ WebApplicationContext appContext=WebApplicationContextUtils. getWebApplicationContext(this.getServlet().getServletContext()); StudentManagerService stdm=(StudentManagerService)appContext. getBean("stdServiceManager"); stdm.bus_method(); return mapping.findForward("chenggong"); } catch(StudentManagerException e){ System.err.println("action execute service exception!"); return mapping.findForward("shibai"); } } }
运行程序:启动服务器,并部署.进入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层捕获,这样我们就可以手动编码的灵活实现通过业务方法执行的成功和失败来向用户转发不同的页面.
发表评论
-
Spring,Hibernate,ResultSet和事务
2012-03-21 15:30 2928今天研究了一天的关于Spring,Hibernate,Resu ... -
Spring 注入 log4j
2012-01-12 17:21 6364如果打算将Log4j注入Spring的applicationC ... -
Spring 使用RMI
2011-03-02 15:46 6985Spring使用RMI非常简单,甚至比直接使用RMI还简单。 ... -
Spring DaoMethodAfterAdvice使用例子
2011-02-10 19:08 1268该拦截器会在bean的方法执行后被执行 import j ... -
Spring MethodBeforeAdvice使用例子
2011-02-10 19:05 14351MethodBeforeAdvice该拦截器会在调用dean的 ... -
Spring ThrowsAdvice使用例子
2011-02-10 19:01 9426ThrowsAdvice用于拦截异常 import ja ... -
Spring 消息注册发布的例子
2011-01-19 16:26 1403消息注册发布模式是我们常用的设计模式,Spring也实现了这个 ... -
FileSystemResource 参数为什么必须是绝对路径
2011-01-19 09:22 4554在使用FileSystemResource时,发现FileSy ... -
Spring的价值
2010-11-08 09:59 15411. Spring是一个非侵入性(non-invasive)框 ... -
Spring和iBatis整合的例子
2010-09-26 16:43 11005OR Mapping的思想相信不用多说大家都明白了,在这里我选 ... -
抛弃EJB(EJB2.0,EJB3.0,EJB4.0)
2010-09-25 17:28 9920关键词:EJB,JEEE,Spring,OO, ... -
J2EE架构图
2010-09-25 11:19 4737以下是J2EE架构图: -
J2EE的核心API与组件(没了EJB,J2EE还剩什么呢)
2010-09-25 10:56 1740J2EE是一种利用Java 2平台来简化企业解决方案的开发、部 ... -
Spring中加载xml配置文件的六种方式
2010-08-31 15:05 41407因为目前正在从事一个项目,项目中一个需求就是所有的功能都是插件 ... -
Spring框架的设计理念与设计模式(9)-策略模式
2010-08-31 13:34 2505关键词:Spring,设计模式,策略模式 上一章:Spring ... -
Spring框架的设计理念与设计模式(8)-代理模式
2010-08-31 13:32 2347关键词:Spring,设计模式,工厂模式,代理模式 上一章:S ... -
Spring框架的设计理念与设计模式(7)-Spring中AOP特性与实现
2010-08-31 13:26 3350关键词:Spring,AOP,Proxy,代理,拦截器 上一章 ... -
Spring框架的设计理念与设计模式(6)-Ioc容器及BeanFactory工厂
2010-08-31 13:20 4753关键词:Spring,Ioc,Bean,Context,Bea ... -
Spring框架的设计理念与设计模式(5)-Core组件
2010-08-31 13:10 2140关键词:Spring,Core,组件, ... -
Spring框架的设计理念与设计模式(4)-Context组件
2010-08-31 13:08 3300关键词:Context,组件,Spri ...
相关推荐
适用企业系统的sturts1.2+spring2.0+jdbc 的架构。 通过TransactionProxyFactoryBean 代理机制和tx/aop两种方式来管理事务的详细demo
包含spring事务管理案例的项目源码和说明文档
自己做的一个小案例,spring 的事务管理小案例,你也可以去以下链接看文章讲解https://blog.csdn.net/zyqblog/article/details/82624441
Spring事务例子,内部包含三个spring事务案例,一个是编程式事务案例,一个声明式事务案例,还有一个最基础的事务案例,需要的可以下载
完整的例子,成功运行. 配好mysql数据库后,可以直接main方法测试事务.
讲述spring事务机制,aopafter,aopbefore,aopmethodintercept,4个例子
JavaEE spring半自动bean管理事务案例
spring使用注解进行事物管理例子,里面有说明.
spring事务_案例_PPT 一、事务传播机制的demo案例,内容包括: 1.业务代码列举7种事务传播机制的情况,每个测试方法都附带日志分析记录、使用场景和实际场景,小白也能看得懂!!! 2.在测试类Test包下,使用juniter...
针对Java Spring 框架的核心技术场景案例,AOP和事务处理部分的应用案例,涉及业务层接口万次执行效率,百度网盘密码数据兼容处理和转账业务追加日志三个案例
自己做的一个简单的spring运用实例,主要是关于事务回滚的一个小例子,希望对还在纠结事务回滚的童靴有点帮助。。。
spring+mybatis+atomikos,java分布式事务。 由于网上的多数据源事务的帖子大多是2010年以前的,现在spring都已经到4.X了,有些类已经弃用了。 原先很多都是用jotm实现的,但是由于spring的升级,totm的本地化实例...
spring 的声明式事务处理的简单例子。我已经测试过能用,能回滚。但例子是入门级别的,如果需要学更高深的请绕道。
Spring+Mybatis+MySql+Maven 简单的事务管理案例.rar
声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。spring注解事务实现demo
这里是Spring的一个Nested事务的代码及数据库文件,因为NESTED资源很少,这里作出了一个通俗易懂的 让需要者下载。
这份文档以例子的形式讲诉了Spring对事务支持的知识,希望可以帮助学习的人!
Spring3.0配置多个事务管理器(即操作多个数据源)的方法 大多数项目只需要一个事务管理器。然而,有些项目为了提高效率、或者有多个完全不同又不相干的数据源,最好用多个事务管理器。机智的Spring的Transactional...
ibatis 完美例子 一对多 批处理 事务 和 spring struts2集成 ,一朵多 插入1万条数据,不到2秒,备注不包含类库
1.创建第一个 Spring 程序案例 2.Spring IoC案例 3.Spring Bean案例 4.Spring 表达式语言案例 5.Spring xml 配置案例 6.Spring Annontation案例 7.Spring 泛型依赖注入案例 8.Spring AOP案例 ...10.Spring 事务案例