`

SPRING事务实现

    博客分类:
  • java
阅读更多

事务传播行为种类

Spring在TransactionDefinition接口中规定了7种类型的事务传播行为,

它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播:

表1事务传播行为类型

事务传播行为类型

说明

PROPAGATION_REQUIRED

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

PROPAGATION_SUPPORTS

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

PROPAGATION_MANDATORY

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

PROPAGATION_REQUIRES_NEW

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

PROPAGATION_NOT_SUPPORTED

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

PROPAGATION_NEVER

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

PROPAGATION_NESTED

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

 

ibatis spring 事务实现
1.配置动态数据源-根据KEY路由

<bean id="dataSource" class="com.xiao.AbstractRoutingDataSource">
        <property name="targetDataSources">
            <map key-type="java.lang.String">
                <entry key="db2" value-ref="ds-db2" />
                <entry key="sqlserver" value-ref="ds-sql" />
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="ds-db2" />
    </bean>  

  
2.配置事务

<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="insert*" propagation="REQUIRED" rollback-for="Throwable" />
            <tx:method name="delete*" propagation="REQUIRED" rollback-for="Throwable" />
            <tx:method name="update*" propagation="REQUIRED" rollback-for="Throwable" />
            <tx:method name="toggle*" propagation="REQUIRED" rollback-for="Throwable" />
            <tx:method name="query*" read-only="true" />
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut id="servicePointcut" expression="execution(* com.xiao..*ServiceImpl.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="servicePointcut" />
        <!-- <aop:advisor advice-ref="txAdvice" pointcut-ref="otherPointcut" /> -->
</aop:config>

 
3.配置IBATIS

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocations">
            <list>
                <value>classpath:/com/xiao/sqlmap-config.xml</value>
               
            </list>
        </property>
        <property name="dataSource" ref="dataSource" />
        <property name="lobHandler" ref="lobHandler" />
</bean>


4.注解事务配置
XML加上  <tx:annotation-driven transaction-manager="transactionManager"/>
在实现类加上这个
@Transactional(propagation=Propagation.NOT_SUPPORTED,rollbackFor=RuntimeException.class)

问题:事务方法中,多个DAO的连接用的应该是同一个connection,SPRING是如何让sqlMapClient的connection和
transactionManager中一致的呢?
分析:可以看到它们用到的是同一个数据源。在SqlMapClientFactoryBean.afterPropertiesSet中会将datasource封装成
TransactionAwareDataSourceProxy一个代理。代理了getConnection方法。
实现细节见DataSourceUtils.doGetConnection ,该方法从当前线程中取线程本地数据(ThreadLocal)MAP,key为数据源,
值为连接,这个如果是事务中,事务的AOP会在进入事务方法前放入这个连接。所以取的连接是同一个。

问题:事务中切换动态数据源切换没用?
分析:根据上面分析,取连接时取的是进入事务方法前设置的连接,所以不行。AbstractRoutingDataSource实际是getConnection
方法动态切换数据源,但这个方法被代理了。而XML配置的DAO和事务的数据源是同一个。

事务分析:
TransactionInterceptor拦截事务方法,第一次进入,当前线程对应的ConnectionHolder为空,
调用doBegin方法,生成一个新的数据库连接ConnectionHolder,事务Transact类设置为newConnectionHolder
属性为TRUE,标记这个Transact为第一次,如果是第一次的Transact,绑定ConnectionHolder,到线程本地上下文
中,如果事务方法中还是嵌套事务情况,假设传播级别是PROPAGATION_REQUIRED(用以前的事务),进入嵌套事务方法时,连接取的
还是第一次的ConnectionHolder,但Transact类设置为newTransaction false(用来区分事务是否要提交);

Propagation.NOT_SUPPORTED:会将之前的事务挂起,当前线程的连接清空;NOT_SUPPORTED方法里的后续的SQL会直接提交,如果前后操作的SQL是同一条数据,
会引起死锁,前面的事务锁住了数据,后续事务无法提交。
Propagation.REQUIRES_NEW:会将之前的事务挂起,新建一个事务,当前线程的连接设置成新事务的数据库连接;新事务提交后,恢复之前的事务,当前线程的数据库连接
设置成恢复事务的连接。保证第一个事务的SQL用的是同一个连接。

分享到:
评论

相关推荐

    spring事务的底层实现流程图

    spring事务的底层实现流程图 spring事务的底层实现流程图 spring事务的底层实现流程图 spring事务的底层实现流程图 spring事务的底层实现流程图 spring事务的底层实现流程图 spring事务的底层实现流程图 spring事务...

    spring事务管理几种方式代码实例

    spring事务管理几种方式代码实例:涉及编程式事务,声明式事务之拦截器代理方式、AOP切面通知方式、AspectJ注解方式,通过不同方式实例代码展现,总结spring事务管理的一般规律,从宏观上加深理解spring事务管理特性...

    Spring事务管理Demo

    Spring事务管理Demo

    Spring事务原理、Spring事务配置的五种方式

    Spring事务原理、Spring事务配置的五种方式

    Spring2.5实现事务管理(本地事务、分布式事务).doc

    Spring2.5实现事务管理(本地事务、分布式事务).doc

    spring编程式事务实现

    演示了spring编程式事务的实现,通过TransactionTemplate模板进行事务控制

    Spring JDBC与事务管理

    3、了解Spring事务管理的3个核心接口; 4、了解Spring事务管理的两种方式; 5、掌握基于XML和Annotation的声明式事务管理的使用。 二.实验内容 (1)使用Spring JDBC实现书店的购书过程,即有如下一个BookShopDao接口...

    spring基于AOP实现事务

    演示了spring基于AOP代理TransactionProxyFactoryBean实现事务

    Spring分布式事务实现

    JOTM使用包 博文链接:https://log-cd.iteye.com/blog/807607

    spring注解事务实现demo

    声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。spring注解事务实现demo

    spring事务以及分布式事务实现.zip

    spring事务以及分布式事务实现.zip one-data-source 单数据源事务 two-data-source 多数据源事务 模块包括 多数据源配置方法 使用atomikos管理多数据源事务 多数据源事务结合Druid数据库连接池 代码包括声明式事务和...

    spring整合hibernate实现事务处理

    spring整合hibernate实现事务处理 1.spring整合hibernate实现事务处理-注解方式 2.spring整合hibernate实现事务处理-XML方式

    spring 自定义事务管理器,编程式事务,声明式事务@Transactional使用

    本代码使用H2内存数据库演示spring事务使用,包括编程式事务,声明式事务@Transactional使用,自定义事务事务注解实现自定义事务管理器

    spring事务操作试验

    spring事务操作试验 博客地址:https://blog.csdn.net/u010476739/article/details/99130972

    深入理解Spring事务原理

    主要带领大家深入理解Spring事务原理,Spring事务的传播属性

    Spring事务优缺点及使用详解.docx

    事务简介 二、程序举例环境搭建 o1. 创建数据表 ...三、使用 Spring 的事务注解管理事务 o1. 声明事务管理器 o2. 开启注解驱动 o3. 完整Spring配置文件 o4. 业务层 public 方法加入事务属性 o5. 测试

    Spring三种事务测试实现.zip

    Spring项目,数据库用mysql,整合Mybatis,需要自己创建数据库testinnodb,以及两张表Account,int id, int account,表Log,int id ,...三种事务,手动实现事务,利用AOP实现,以及声明式事务,lib中有所有的jar。

    JavaEE spring事务操作环境和基本功能搭建

    JavaEE spring事务操作环境和基本功能搭建

    Spring中事务用法示例及实现原理详解

    主要给大家介绍了关于Spring中事务用法示例及实现原理的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    spring五种事务配置demo

    测试spring事务管理 搭建了ssh框架的web工程 本工程用到的数据库表很简单 user(id, name) 可自行创建 本例所有的事务放在service层进行管理,方法中间抛出运行时异常以测试是否回滚 Spring配置文件中关于事务...

Global site tag (gtag.js) - Google Analytics