关于分布式事务那点事

我想用spring自动切换数据源来实现分布式的事务

主要是想懒一下,两个数据源下有相同两个表时省着弄两个dao实体类,(内容一样但dao的名字不同才行)

上我的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--大数据的数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close" p:dbType="sqlserver" p:driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" p:url="${jdbc.shuju.url}" p:username="${jdbc.shuju.username}" p:password="${jdbc.shuju.password}" p:filters="log4j" p:useGloalDataSourceStat="true" p:validationQuery="SELECT 'x';" p:testWhileIdle="true" p:testOnBorrow="false" p:testOnReturn="false">
        <property name="connectProperties">
            <props>
                <prop key="allowMultiQueries">true</prop>
            </props>
        </property>
    </bean>

    <!--2.0数据源-->
    <bean id="dataSourceZhu2" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close" p:dbType="sqlserver" p:driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" p:url="${jdbc.zhu.url}" p:username="${jdbc.zhu.username}" p:password="${jdbc.zhu.password}" p:filters="log4j" p:useGloalDataSourceStat="true" p:validationQuery="SELECT 'x';" p:testWhileIdle="true" p:testOnBorrow="false" p:testOnReturn="false">
        <property name="connectProperties">
            <props>
                <prop key="allowMultiQueries">true</prop>
            </props>
        </property>
    </bean>

    <!--统一权限数据源-->
    <bean id="dataSourceUR" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close" p:dbType="sqlserver" p:driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" p:url="${jdbc.role.url}" p:username="${jdbc.role.username}" p:password="${jdbc.role.password}" p:filters="log4j" p:useGloalDataSourceStat="true" p:validationQuery="SELECT 'x';" p:testWhileIdle="true" p:testOnBorrow="false" p:testOnReturn="false">
        <property name="connectProperties">
            <props>
                <prop key="allowMultiQueries">true</prop>
            </props>
        </property>
    </bean>
    <!--数据源交给Spring控制-->
    <bean id="multipleDataSource" class="com.nxin.common.autodatasource.MultipleDataSource">
        <property name="defaultTargetDataSource" ref="dataSource"/>
        <property name="targetDataSources">
            <map>
                <entry key="zhu2" value-ref="dataSourceZhu2"/>
                <entry key="role" value-ref="dataSourceUR"/>
                <entry key="default" value-ref="dataSource"/>
            </map>
        </property>
    </bean>
    <!-- 配置数据源切换实现类-->
    <bean id="dataSourceContextHolder"
          class="com.nxin.common.autodatasource.DataSourceContextHolder" />

    <!-- 切面还原默认数据源(执行完service层后切回)-->
    <aop:config>
        <aop:aspect id="dataSourceHolderAdviceAspect"
                    ref="dataSourceContextHolder">
            <aop:after-returning method="setDefaultDbType"
                       pointcut="execution(public * com.nxin.*.*.service..*.*(..))" />

            <aop:after-throwing method="clearDbType"
                       pointcut="execution(public * com.nxin.*.*.service..*.*(..))" />
        </aop:aspect>
    </aop:config>

    <!--mybatissessionFactoryMapper配置-->
    <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" p:dataSource-ref="multipleDataSource" p:typeAliasesPackage="com.nxin.shuju.user.bo,com.nxin.shuju.application.bo" p:mapperLocations="classpath*:/config/dao/*.xml"/>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" p:basePackage="com.nxin.shuju.*.dao"/>

    <!--mybatis的事务配置-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="multipleDataSource"/>
    <tx:advice id="advice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException"/>
            <tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException"/>
            <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>
            <tx:method name="add*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>
            <tx:method name="find*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>
            <tx:method name="get*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>
            <tx:method name="select*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(public * com.nxin.*.*.service..*.*(..))" /> <!--把事务控制在Service-->
        <aop:advisor pointcut-ref="pointcut" advice-ref="advice"/>
    </aop:config>
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate" p:transactionManager-ref="transactionManager"/>

    <bean id="ucTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="multipleDataSource"/>

</beans>

但这样问题来了,我把事务处理控制在service层,所以就要在control层切换到指定数据源,例如:

DataSourceContextHolder.setDbType("role");

我曾尝试在service层被事务拦截的方法中切数据源,但根本就无效,执行会报错,找不到对应数据库表

但是不被事务拦截的方法中是可以自由切换数据源,程序执行没有问题。


这tm是为毛啊???

后来想想,既然被事务拦截,一定是事务开启就要指定sessionFactory的数据源唯一连接所以在进入service处理之前就要指定好数据源,

向上面我的做法!!!放在control层


所以想想,这种切数据源的做法是不适合分布式事务的!不过要只是切库查询应该还是没有太大问题的!

要分布式事务,还得用老老实实用jta阿!!!

不过这里我用的

DataSourceTransactionManager

不知道要是用JtaTransactionManager是不是就好用尼!!!

我说的意思是自动切数据源  

multipleDataSource+JtaTransactionManager

有这样弄过的吗? 告诉告诉本懒人!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值