本文主要是在看了 关于spring声明式事务管理异常处理的测试和小结
http://www.iteye.com/topic/34867一文以后想写的,而且前段时间与jbpm整合的时候才发现自己的事务设置一直有问题,根本无法回滚(汗,都是网络上照抄的,没测试),再加上它的使用的spring版本1.2,所以觉得有必要自己再测试,加深影像。
对事务有任何不清楚的,可以参考一下这个 http://bhsc-happy.iteye.com/blog/288983
开发环境:
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层接口:
public interface Student1Service {
void addStudent1(Student1 stu);
}
public interface StudentSService {
void addStudent2(Student2 stu) throws SaveException;
}
Service实现
public void addStudent1(Student1 stu) {
stufDAO.insertStuF(stu);
}
public void addStudent2(Student2 stu) throws SaveException {
String[] aa={"ww","ww","ww"};
for(int i=0;i<5;i++){ //出错
System.out.println(aa[i]);
}
stusDAO.insertStuS(stu);
}
DAO层接口
public interface StudentFDAO {
void insertStuF(Student1 stu);
}
public interface StudentSDAO {
void insertStuS(Student2 stu);
}
DAO实现
public void insertStuF(Student1 stu) {
getHibernateTemplate().save (stu);
}
public void insertStuS(Student2 stu) {
getHibernateTemplate().save (stu);
}
Action
public String execute() throws Exception{
Student1 sti=new Student1(stu1Name,stu1Address);
Student2 stu=new Student2(stu1Name,stu1Address);
try{
studentfService.addStudent1(sti);
studentsService.addStudent2(stu);
}catch(DataAccessException e){
System.out.println(“error”);
return “failer”:
}
return SUCCESS;
}
JSP
<form action="testaction.action" method="POST">
<table>
<tr><td>名:</td><td><input type="text" value="stu1Name" name="stu1Name"></td></tr>
<tr><td>地址:</td><td><input type="text" value="stu1Address" name="stu1Address"></td></tr>
<Tr><td></td><td><input type="submit" value="提交" style="width:80px"></td></Tr>
</table>
</form>
配置文件
<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>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<!-- 定义BeanNameAutoProxyCreator-->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>st1Service</value>
<value>stsService</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</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这个运行时异常,不过在业务层中也有可能抛出一些其他的运行时异常,那么这时候在一些简单的项目中,我们直接用下面的方式也未尝不可:
try{
…….
………
……..(可能会有其他运行时异常,并不仅仅是DataAccessException)
}catch(Exception e){
log.error(“error”);
throw new CheckedException(“error”); //抛出受检查异常
}
然后在Action层捕捉这个受检查异常
try{
service.method();
}catch(CheckedException e){
}
这个异常,它是可以被调用者正确处理的。返回相应的提示。当然,如果抛出CheckException,那么Spring声明式事物的时候就应该加上-Exception参数,前面已经提到。
当然在一些业务逻辑比较复杂,并且要根据复杂的逻辑返回不同的试图的时候,这样整个的try{}catch(){}就不合适了,
这时候应该将不正常的事件流转换为运行时异常,并且在方法声明中详细的说明该方法可能会抛出的unChekced异常。由调用者自己去决定是否捕获unChecked异常,返回相应的视图。
总结:
1.一般DAO中不捕捉异常也不抛出异常
2.至于Service层和Action层,是在service层抛出CheckException然后由action捕捉,还是在service中全部采用unCheckException,然后在action中有选择的捕捉或者都不捕捉就要看你自己的选择了, 个人认为逻辑比较简单的可以选择前者,比较复杂就选择后者。
3.禁忌捕捉异常而不做任何处理(如果是dao层或者service层,最好抛出),不然很有可能造成事务处理失败。
分享到:
- 2008-12-08 19:56
- 浏览 2439
- 评论(1)
- 论坛回复 / 浏览 (1 / 4484)
- 查看更多
相关推荐
在实际开发中,理解这部分源码有助于我们更深入地掌握Spring事务管理的工作原理。 至于工具,开发者可以使用诸如IntelliJ IDEA这样的IDE,其中集成的调试工具可以帮助我们跟踪代码执行流程,查看事务状态的变化,...
关于标签中的“源码”,探究Spring事务管理的源码可以深入理解其实现原理。例如,分析TransactionProxyFactoryBean和AOP代理是如何实现声明式事务的;查看PlatformTransactionManager接口及其实现类,如...
- **Spring 容器**:探究 BeanFactory 和 ApplicationContext 的区别,以及如何通过它们管理对象的生命周期。 - **数据访问**:了解 Spring 如何整合各种 ORM 和 OXM 框架,以及如何实现数据访问层的事务管理。 ...
第10章:对实际应用中Spring事务管理各种疑难问题进行透彻的剖析,让读者对Spring事务管理不再有云遮雾罩的感觉。 第11章:讲解了如何使用Spring JDBC进行数据访问操作,我们还重点讲述了LOB字段处理、主键产生...
例如,你可以看到如何通过XML配置或Java配置实现依赖注入,查看AOP的实现原理,探究Spring MVC的请求处理流程,学习Spring对不同数据访问技术的集成方式,以及如何利用Spring Boot简化应用的初始化。此外,研究源码...
在这个源码包中,我们可以深入探究Spring的核心机制,理解它如何实现依赖注入、AOP(面向切面编程)、事务管理等关键功能。 首先,让我们关注依赖注入(Dependency Injection,简称DI)。Spring通过DI帮助我们解耦...
6. **事务管理**:研究PlatformTransactionManager接口和相关的事务策略,理解Spring如何实现声明式事务管理。 7. **数据访问集成**:分析JdbcTemplate、HibernateTemplate等工具类,了解Spring如何简化数据库操作...
在5.2.25.RELEASE中,Spring Web模块是另一个重要的部分,它包含了处理HTTP请求、构建RESTful服务等功能。DispatcherServlet是Web应用的入口,负责路由请求到相应的处理器。Spring MVC提供了一套完整的MVC框架,包括...
这个压缩包"spring-framework-2.5.4源码.rar"包含了Spring框架的核心组件和相关源代码,特别是"src"目录下的文件,这将使我们有机会探究Spring如何处理IoC(Inversion of Control)、AOP(Aspect Oriented ...
3. **DispatcherServlet和HandlerMapping**:探究Spring MVC如何处理HTTP请求,如何根据请求映射到相应的处理器。 4. **Transaction Management**:分析Spring的事务管理机制,包括编程式和声明式事务,理解事务的...
在Spring 4.3.12源码中,我们可以深入探究以下关键知识点: 1. **IoC(Inversion of Control)容器**:这是Spring的核心,负责管理对象的生命周期和依赖关系。通过XML配置或基于注解的方式,IoC容器能够自动创建和...
在这个文档和源码集合中,我们可以深入探究Spring 2.0的核心概念和技术细节。 首先,`.chm`文件是Windows的帮助文件格式,这里包含的是Spring 2.0的官方文档。文档通常会详细介绍框架的架构、配置、API以及如何在...
"Spring-Integration-in-Action" 是一本深入探讨 Spring Integration 实战的书籍,其源码提供了宝贵的教育资源,让我们能够深入探究这个强大的框架。 首先,我们来看看 Spring Integration 的核心概念: 1. **通道...
同时,结合JDK库的使用,可以深入探究Spring如何利用Java的特性来实现其强大的功能。 总的来说,这个压缩包为学习Spring源码提供了一套完整的资源。从IoC到AOP,从数据访问到Web开发,通过调试代码和实例,我们可以...
- **MVC框架内部工作原理**:了解Spring MVC处理请求的具体流程。 #### 学习资料 - **官方文档**:Spring官方文档是最权威的学习资料,包含详细的API文档和技术指南。 - **社区论坛**:Stack Overflow、GitHub等...
让我们一起深入探究Spring源码中的关键知识点。 首先,Spring的核心组件之一是IoC容器。IoC容器通过反转控制权,使得对象的创建和依赖关系的管理交由框架处理。在Spring源码中,`org.springframework.beans.factory...
2. **面向切面编程**:Spring的AOP功能允许我们在不修改代码的情况下添加额外的行为,如日志记录、事务管理等。这使得业务逻辑和系统服务的分离更加明确。 3. **Spring MVC**:Spring提供的Model-View-Controller...
3. **Spring MVC**:探究Spring的Web MVC框架,如何创建控制器、模型、视图和视图解析器,以及Spring Boot中自动配置的MVC特性。 4. **数据访问集成**:学习Spring如何与各种数据库进行交互,包括JDBC模板、...
4. spring-aop:面向切面编程模块,支持声明式事务、日志等切面功能。 5. spring-web:Web层支持,包括Servlet、Filter、MVC等。 6. spring-jdbc:数据库操作支持,简化JDBC操作。 7. spring-orm:ORM集成,如...