多数据源的事务一致解决

参考链接: link

  1. 事务管理器

    <bean id="transactionManagerivc" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="ivcDataSource"></property>
    </bean>
    
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    

    系统使用多数据源,此处以两个数据源做测试

  2. 注解

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @Inherited
    public @interface MultiTransactional {
        String[] transactionManagers();
    }
    

    此处Inherited为了继承可用,可有可无

  3. asp

    @Aspect
    @Component
    public class TestAspect {
        private static final ThreadLocal<Stack<Pair<DataSourceTransactionManager, TransactionStatus>>> THREAD_LOCAL = new ThreadLocal<>();
        @Autowired
        private ApplicationContext applicationContext;
    
        private DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        {
            // 非只读模式
            def.setReadOnly(false);
            // 事务隔离级别:采用数据库的
            def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
            // 事务传播行为
            def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        }
    
        @Pointcut("@annotation(cn.hsa.htp.hitotax.CBXX001.service.MultiTransactional)")
        public void pointcut(){}
    
        @Before(value = "pointcut() && @annotation(transactional)")
        public void before(MultiTransactional transactional) {
            // 根据设置的事务名称按顺序声明,并放到ThreadLocal里
            String[] transactionManagerNames = transactional.transactionManagers();
            Stack<Pair<DataSourceTransactionManager, TransactionStatus>> pairStack = new Stack<>();
            for (String transactionManagerName : transactionManagerNames) {
                DataSourceTransactionManager transactionManager = applicationContext.getBean(transactionManagerName, DataSourceTransactionManager.class);
                TransactionStatus transactionStatus = transactionManager.getTransaction(def);
                pairStack.push(new Pair(transactionManager, transactionStatus));
            }
            THREAD_LOCAL.set(pairStack);
        }
        @AfterReturning("pointcut()")
        public void afterReturning() {
            // ※栈顶弹出(后进先出)
            Stack<Pair<DataSourceTransactionManager, TransactionStatus>> pairStack = THREAD_LOCAL.get();
            while (!pairStack.empty()) {
                Pair<DataSourceTransactionManager, TransactionStatus> pair = pairStack.pop();
                pair.getKey().commit(pair.getValue());
            }
            THREAD_LOCAL.remove();
        }
    
        /**
         * 回滚事务
         */
        @AfterThrowing(value = "pointcut()")
        public void afterThrowing() {
            // ※栈顶弹出(后进先出)
            Stack<Pair<DataSourceTransactionManager, TransactionStatus>> pairStack = THREAD_LOCAL.get();
            while (!pairStack.empty()) {
                Pair<DataSourceTransactionManager, TransactionStatus> pair = pairStack.pop();
                pair.getKey().rollback(pair.getValue());
            }
            THREAD_LOCAL.remove();
        }
    }
    

4.测试

    @Override
    @MultiTransactional(transactionManagers = {"transactionManagerivc", "transactionManager"})
    public ReturnT<String> execute(String s) throws Exception {
        try {
            String psnNo = "123";
            String psnName = "456";
            Integer integer1 = ylLhjy0318DAO.insertSheet1(psnNo, psnName);
            XxlJobLogger.log("" + integer1);
            Integer integer2 = hiTestDAO.insertSheet1(psnNo, psnName);
            XxlJobLogger.log("" + integer2);
        }catch (Exception e){
            XxlJobLogger.log("######### error: " + e, e);
            LOGGER.info("######### error: ", e);
            XxlJobLogger.log(e);
            throw e;
        }
        return SUCCESS;
    }

测试方法很简单,随便建两张表,设置主键,然后重复插入数据导致报错

5.遇到的坑
在catch中,如果不throw,则直接进入AfterReturning,故必须throw才能生效

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值