spring service层事务管理小结


前言:
    选择spring作为开发的框架,很大一部分因素是spring框架完善的事务处理机制,spring的事务实现主要分为两种,一种是基于Dao层,另一种是基于Service层,前者是针对单个dao的持久化操作做了事务控制,控制粒度比较小,后者则是基于业务的原则性需求,将一个原子性业务的操作做了事务控制,本文主要针对service层事务配置进行说明:

方法一:基于注解的service层事务配置

spring-mybatis.xml中做如下配置:

1、首先配置数据源:
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close" lazy-init="false">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
</bean>

2、事务管理 : DataSourceTransactionManager dataSource:引用上面定义的数据源 
<bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
</bean> 

3、使用声明式事务 transaction-manager:引用上面定义的事务管理器 
<tx:annotation-driven transaction-manager="transactionManager" />

service层方法添加如下注解:

@Transactional( rollbackFor={Exception.class})
例:
@Service("cmdbOrderService")
public class  CmdbOrderServiceImpl implements CmdbOrderService {
    //@Transactional( rollbackFor={Exception.class})
    public boolean disposeCmdbOrder(CmdbOrder cmdbOrder) {
        //........
    }
}

第二种方法:基于AOP代理的service层事务配置

1、首先配置数据源:
    <context:property-placeholder location="classpath:jdbc.properties" />
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close" lazy-init="false">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>

2、事务管理 : DataSourceTransactionManager dataSource:引用上面定义的数据源 
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean> 

3 配置事物的具体内容,
    <tx:advice id="transactionAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="append*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="batchSave*" propagation="REQUIRED" />
            <tx:method name="batchDel*" propagation="REQUIRED" />
            <tx:method name="refreshUnrecovery*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="modify*" propagation="REQUIRED" />
            <tx:method name="edit*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="remove*" propagation="REQUIRED" />
            <tx:method name="repair" propagation="REQUIRED" />
            <tx:method name="delAndRepair" propagation="REQUIRED" />
            <tx:method name="create*" propagation="REQUIRED" />
            <tx:method name="dispose*" propagation="REQUIRED" />

            <tx:method name="get*" propagation="SUPPORTS" />
            <tx:method name="find*" propagation="SUPPORTS" />
            <tx:method name="load*" propagation="SUPPORTS" />
            <tx:method name="search*" propagation="SUPPORTS" />
            <tx:method name="datagrid*" propagation="SUPPORTS" />

            <tx:method name="*" propagation="SUPPORTS" />
        </tx:attributes>
    </tx:advice>

4 动态数据源事物aop,当service层方法满足上述正则,则开启事物
    <aop:config  proxy-target-class="true">
        <aop:pointcut id="transactionPointcut" expression="execution(*  com.wutongyu.service..*Impl.*(..))" />
        <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice"      order="2"/>
    </aop:config>

注意:捕获异常 事务的处理

    默认情况下,spring事务只在发生未被捕获的RuntimeException时才回滚,如果有通过try-catch捕获异常,事物不会生效;只有在抛出 RuntimeException时,事物才会生效,如果要求方法内部必须进行捕捉,怎么处理呢?
    (1)在catch语句中最后增加throw new RuntimeException(),手动抛出异常,以便aop捕获异常再去回滚,并且在service上层要继续捕获这个异常并处理。
    (2)在service层方法的catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常。

猜你喜欢

转载自blog.csdn.net/wutongyuWxc/article/details/80622562