• spring声明式事务管理方式( 基于tx和aop名字空间的xml配置+@Transactional注解)


    1. 声明式事务管理分类

    声明式事务管理也有两种常用的方式,

    一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。

    显然基于注解的方式更简单易用,更清爽。

    2. spring事务特性

    spring所有的事务管理策略类都继承自org.springframework.transaction.PlatformTransactionManager接口

    其中TransactionDefinition接口定义以下特性:事务隔离级别、事务传播行为、事务超时、事务只读属性、spring事务回滚规则等;

    其实这些特性的介绍,网上一堆,在这我就不再啰嗦了,接下来我只想告诉你到底如何使用。

    3. 声明式事务管理配置两种方式

    如下都将以mybatis为例。

    3.1 基于@Transactional注解的

    1、首先来看一段代码 spring.xml

    <!-- MyBatis begin -->
        <!-- 1、mybatis文件配置,扫描所有mapper文件 -->
        <bean class="org.mybatis.spring.SqlSessionFactoryBean">
            <!-- 设置MyBatis核心配置文件 -->
            <property name="configLocation" value="classpath:resources/mybatis/mybatis-config.xml" />
            <!-- 设置数据源 -->
            <property name="dataSource" ref="dataSource" />
            <!-- 它表示我们的Mapper文件存放的位置,当我们的Mapper文件跟对应的Mapper接口处于同一位置的时候可以不用指定该属性的值。 -->
            <property name="mapperLocations" value="classpath:/mappings/**/*.xml" />
            <!-- 那么在Mapper文件里面就可以直接写对应的类名 而不用写全路径名了  -->
            <!-- 跟mybatis中<typeAliases>作用一样 -->
            <!-- <property name="typeAliasesPackage" value="com.jeenotes.ssm.pojo"/> -->
        </bean>
    
        <!-- 2、spring与mybatis整合配置,扫描所有dao,在单数据源的情况下可以不写sqlSessionFactoryBeanName -->
        <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
           <!-- 设置Mapper扫描包,注意扫描的是java-dao-接口文件,不是xml -->
        <property name="basePackage" value="com.jeenotes.ssm.dao" />
        </bean>
    
        <!-- 3、定义事务 -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>
        
        <!-- 4、开启事务控制的注解支持,配置 Annotation 驱动,扫描@Transactional注解的类定义事务  -->
        <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
     <!-- MyBatis end -->

    这个文件时spring和mybatis配置中的,细心的你可能会发现,这1234,4个配置之间通过id存在关联关系的。

    2、添加tx名字空间

    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xsi:schemaLocation="http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"

    补充一下:添加到spring.xml上边的头部分,至于不明白xmlns,xmlns:xsi,xsi:schemaLocation等含义的同学,可以考虑看一下这篇文章了。

    关于XML文档的xmlns、xmlns:xsi和xsi:schemaLocation详解

    3、基于注解式小结

    综上,MyBatis自动参与到spring事务管理中,无需额外配置,只要org.mybatis.spring.SqlSessionFactoryBean引用的数据源与DataSourceTransactionManager引用的数据源一致即可,也就是那些id要对应起来,否则事务管理会不起作用。

    3.2 基于tx和aop名字空间的xml配置式

    同样还是以mybatis为例,主要为aop切面配置,只看xml就可以了

    注意:通常这种方式的配置我们都需要再创建一个xml文件:spring-trans.xml

    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd 
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd"
    > <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 数据源 --> <property name="dataSource" ref="dataSource" /> </bean> <!-- 通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 传播行为 --> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="create*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="find*" propagation="SUPPORTS" read-only="true" /> <tx:method name="select*" propagation="SUPPORTS" read-only="true" /> <tx:method name="get*" propagation="SUPPORTS" read-only="true" /> </tx:attributes> </tx:advice> <!-- 切面 --> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.jeenotes.ssm.service.*.*(..))" /> </aop:config> </beans>

    4. 声明式事务配置总结

    通过上方步骤三的配置相信你已经学会如何配置声明式事务管理了,最后总结一下:

    1、首先要明确上边的两种方式都是声明式事务管理的表现形式,思路千万不要乱。

    2、两种方式配置后的使用规则

    2.1、通过3.1第一种的配置,以后就可以在类、或者方法上使用@Transactional注解了(相信有的小伙伴还不知道该注解可以用在方法或者类上边吧),

    加入该注解的类或者方法,在执行过程中就会加入到同一事务中,同生共死。

    通常你会看到这样的写法,@Transactional(readOnly = true),不得不补充一下@Transactional的属性

    属性类型描述
    value String 可选的限定描述符,指定使用的事务管理器
    propagation enum: Propagation 可选的事务传播行为设置
    isolation enum: Isolation 可选的事务隔离级别设置
    readOnly boolean 读写或只读事务,默认读写
    timeout int (in seconds granularity) 事务超时时间设置
    rollbackFor Class对象数组,必须继承自Throwable 导致事务回滚的异常类数组
    rollbackForClassName 类名数组,必须继承自Throwable 导致事务回滚的异常类名字数组
    noRollbackFor Class对象数组,必须继承自Throwable 不会导致事务回滚的异常类数组
    noRollbackForClassName 类名数组,必须继承自Throwable 不会导致事务回滚的异常类名字数组

     

    2.2、通过3.2第二种的配置,会对方法名有要求,在上方的配置中举个例子,

    <tx:method name="save*" propagation="REQUIRED" />,比如如果saver中方法名是以save开头的就会加入事务。

    @Service
    public class ItemCatServiceImpl implements ItemCatService {
    
        @Autowired
        private TbItemCatDao itemCatDao;
        
        @Override
        public void saveItemCat(EasyUITreeNode node) {
            
            itemCatDao.save(node);
            
        }
    }

    不知道你是否会好奇propagation属性,该属性里的属性值你可以理解成@Transactional注解属性值,如下补充一下

    事务传播行为类型

    说明

    REQUIRED

    如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。

    SUPPORTS

    支持当前事务,如果当前没有事务,就以非事务方式执行。

    MANDATORY

    使用当前的事务,如果当前没有事务,就抛出异常。

    REQUIRES_NEW

    新建事务,如果当前存在事务,把当前事务挂起。

    NOT_SUPPORTED

    以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

    NEVER

    以非事务方式执行,如果当前存在事务,则抛出异常。

    NESTED

    如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类 似的操作。

    3、项目中的使用选择。

    在实际项目中,这两种方式采用哪一种实现效果都一样,其实到底采用哪一种要看项目需求,重要的是往往并不是你去配置,所以你只需要知道有这两种方式就行喽。

     

    本文地址:http://www.cnblogs.com/niceyoo/articles/8732891.html

     

  • 相关阅读:
    CSP内容安全策略总结及如何抵御 XSS 攻击
    CORS跨域资源共享总结
    web安全总结
    小知识随手记(八)
    内存泄漏问题总结
    Vue中插槽slot的使用
    Git常用命令、及常见报错处理:You have not concluded your merge (MERGE_HEAD exists)、清理无效的远程追踪分支
    render函数、createElement函数与vm.$slots
    Redis集群(二):Redis的安装
    Shell命令_文件系统常用命令df、du
  • 原文地址:https://www.cnblogs.com/niceyoo/p/8732891.html
Copyright © 2020-2023  润新知