1.2 spring 事务

本文详细介绍了如何在Spring MVC中利用AOP和XML配置实现服务层异常的统一处理和事务回滚。包括如何配置事务管理器、切入点表达式、事务属性以及异常处理机制。并通过实例演示了在不同场景下事务的有效性和失效情况,以及如何正确地处理事务边界和异常。

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

例1:springMVC 统一处理service异常回滚:(注这种声明式(配置或者注解)在springMVC中有可能实现,见例1.1)
xml:
   <!-- 定义切面,进行过滤,添加service的方法在事务控制范围。  -->
<aop:config proxy-target-class="true">

<aop:pointcut id="allManagerMethod" expression="execution(* com..*.services.*Service.*(..))" />

<!--com..*表示com包及com包下所有子包;.*Service.*(..)表示以Service结尾的类下的所有方法-->

<aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod" /> 
</aop:config>
 
<!-- 基本事务定义,使用transactionManager作事务管理,默认get* find*方法的事务为readonly,其余方法按默认设置. 默认的设置请参考Spring文档事务一章. -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="find*" read-only="true"/>
<tx:method name="get*"  read-only="true"/>
<tx:method name="qry*"  read-only="true"/>
<tx:method name="query*" read-only="true"/>
<tx:method name="load*" read-only="true"/>
<tx:method name="*" />
</tx:attributes>
</tx:advice>

  <!--  启动加载异常处理的类,用于监听各模块中触发的异常  -->
    <bean id="handlerExceptionResolver" class="com.core.exception.MyHandlerExceptionResolver">
    <property name="defaultErrorView" value="commons/defaultError"/>
    </bean>


HandlerExceptionResolver的实现:
public class MyHandlerExceptionResolver implements HandlerExceptionResolver {

private Logger logger = LoggerFactory.getLogger(getClass());
private String defaultErrorView;
public String getDefaultErrorView() {
return defaultErrorView;
}
public void setDefaultErrorView(String defaultErrorView) {
this.defaultErrorView = defaultErrorView;
}
@SuppressWarnings("unchecked")
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {
logger.error("class = "+handler.getClass());
logger.error("exception = "+ex.getClass());
logger.error("exception = "+ex.getCause());
logger.error("Handle exception: " + ex.getMessage());
Map model = new HashMap();
model.put("ex", ex.getClass().getSimpleName());
model.put("error", ex.getClass()+"<br>"+ex.toString());
return new ModelAndView(defaultErrorView, model);
}
}

注:只可以对unchecked 异常进行回滚(service中不用再添加try快)。对于其他的异常不会进行回滚。不过你也可以通过rollback-for属性进行指定你所要抛出的异常类型。


例1.1:springMVC 经典事务失效问题(applicationContext.xml和springmvc-servlet.xml配置问题)

a.在主容器中(applicationContext.xml),将Controller的注解排除掉 
<context:component-scan base-package="com"> 
  <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> 
</context:component-scan> 
而在springMVC配置文件中将Service注解给去掉 
<context:component-scan base-package="com"> 
  <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> 
  <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" /> 
  </context:component-scan> 
b.参考文章
http://icanfly.iteye.com/blog/778401(good)
http://hi.baidu.com/wangbeiyong/item/e73728e5644e1d0d64db0079
http://hi.baidu.com/wangbeiyong/item/e73728e5644e1d0d64db0079


----------------------------

例二:看看一个ssh项目中的事务配置例子:
xml:事务配置:
<!-- 定义事务管理器(声明式的事务) -->
<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="get*">PROPAGATION_REQUIRED</prop>
<prop key="find*">PROPAGATION_REQUIRED</prop>
<prop key="load*">PROPAGATION_REQUIRED</prop>
<prop key="query*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="create*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="put*">PROPAGATION_REQUIRED</prop>
<prop key="check*">PROPAGATION_REQUIRED</prop>
<prop key="apply*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>*Service</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
<bean id="entityDao" class="com.test.dao.impl.EntityDaoImpl">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
注意:PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
如上面的配置,就能确保Service中每个方法中的内容在同一个事务中,这些内容有可能有其他的方法,如同下边A2中所有内容在一个事务中,不管是否含有A1


一。
action:
public void a() {

aService.createA2("111",auth);

}

services:
1.//测试一下:services中单个方法抛出异常,会发生回滚
此时事务全在A2中,
    @Override
    public String createA2(String str, Authorization auth){
//this.createA1("11",auth);

TermShop termshop=new TermShop();
termshop.setSerialNo("12");
this.createTermShop(termshop, auth);

TermShop termshop2=new TermShop();
termshop2.setSerialNo("12");
this.createTermShop(termshop2, auth);
if(1==1){
   throw new RuntimeException();
}
return "aaa";

}

2.//测试一下:services中一个方法调用另一个方法,抛出异常,这个事务不会提交,会发生回滚
此时因为配置中service有事务控制,首先在A2中创建事务,当调用A1的时候,因为A2中已经有一个事务,所以不需要重新在A1中创建事务,共用A2创建的事务。(即为A2中所有共用一个事务)
    @Override
    public String createA1(String str, Authorization auth){
TermShop termshop=new TermShop();
termshop.setSerialNo(str);
this.createTermShop(termshop, auth);
return "-----aaa-----";
    }
    
    
    @Override
    public String createA2(String str, Authorization auth){
System.out.println(this.createA1("12",auth));

TermShop termshop=new TermShop();
termshop.setSerialNo("12");
this.createTermShop(termshop, auth);


TermShop termshop2=new TermShop();
termshop2.setSerialNo("12");
this.createTermShop(termshop2, auth);
if(1==1){
   throw new RuntimeException();
}
return "aaa";

}
   
二。    
如果action中这样调用,因为配置事务在services中,此时有两个事务,一个控制A1,一个控制A2
1.如果action中不捕获异常,因为A1发生异常,导致程序中断,所以也不会存入数据。
2.如果action中捕获异常,如下,则当A1发生异常,程序照样运行,A2中会存入数据 (原因:因为为exception的时候,spring异常没法捕获,所以解决方法不用try catch,或者catch的异常为RunException或者DataAccessException,而不是 exception) 

public void a() {
try {
   aService.createA1("111",auth);
} catch (Exception e) {
 e.printStackTrace();
}
aService.createA2("111",auth);

}

services:
    @Override
    public String createA1(String str, Authorization auth){
TermShop termshop=new TermShop();
termshop.setSerialNo("12");
this.createTermShop(termshop, auth);
if(1==1){
  throw new RuntimeException();
}
return "-----aaa-----";
    }
        
    @Override
    public String createA2(String str, Authorization auth){

TermShop termshop=new TermShop();
termshop.setSerialNo("12");
this.createTermShop(termshop, auth);

TermShop termshop2=new TermShop();
termshop2.setSerialNo("12");
this.createTermShop(termshop2, auth);
if(1==1){
  // throw new RuntimeException();
}
return "aaa";

}



    
资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值