1.2 spring 事务

例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";

}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值