栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

轻量级分布式事务-自定义多数据源事务注解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

轻量级分布式事务-自定义多数据源事务注解

一、背景

对于一个方法内,同时操作多个、或者多种类型的数据源时,比如一个MySQL、一个MongoDB,或者两个不同的MySQL,事务管理器只能唯一的场景使用声明式的注解@Transactional 无法保证多个数据源回滚,只能保证单一数据源@Primary回滚,使用编程式的方式去回滚事务,代码侵入太多,使用复杂度高。所以需要自定义注解,实现对多个数据源的管理 二、实现过程 1、自定义注解@MultiDataSourceTransactional

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@documented
public @interface MultiDataSourceTransactional {
    @AliasFor("transactionManagers")
    String[] values() default {"transactionManager", "mongoTransactionManager"};
 
 
    @AliasFor("values")
    String[] transactionManagers() default {"transactionManager", "mongoTransactionManager"};
 
}
2、定义切面
@Slf4j
@Aspect
@Configuration
public class MultiDataSourceTransactionalAspect {
    private static final ThreadLocal>> THREAD_LOCAL = new ThreadLocal<>();
 
 
    @Autowired
    private ApplicationContext applicationContext;
 
    
    private DefaultTransactionDefinition def = new DefaultTransactionDefinition();
 
    {
        log.info("代码块执行 start");
        // 非只读模式
        def.setReadOnly(false);
        // 事务隔离级别:采用数据库的
        def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
        // 事务传播行为
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        log.info("代码块执行 end");
    }
 
 
    @Pointcut("@annotation(你的注解包名.MultiDataSourceTransactional)")
    public void pointcut() {
        log.info("切面");
    }
 
    
    @Before("pointcut() && @annotation(transactional)")
    public void before(MultiDataSourceTransactional transactional) {
        long s = System.currentTimeMillis();
        log.info("before start");
        // 根据设置的事务名称按顺序声明,并放到ThreadLocal里
        String[] transactionManagerNames = transactional.transactionManagers();
        Stack> pairStack = new Stack<>();
        for (String transactionManagerName : transactionManagerNames) {
            PlatformTransactionManager transactionManager;
            // TODO 名字定义为枚举
            if ("mongoTransactionManager".equals(transactionManagerName)) {
                transactionManager = applicationContext.getBean(transactionManagerName, MongoTransactionManager.class);
            } else {
                transactionManager = applicationContext.getBean(transactionManagerName, DataSourceTransactionManager.class);
            }
            TransactionStatus transactionStatus = transactionManager.getTransaction(def);
            pairStack.push(new Pair(transactionManager, transactionStatus));
        }
        THREAD_LOCAL.set(pairStack);
        long e = System.currentTimeMillis();
        log.info("before end  消耗时间:{}  ms", (e - s));
    }
 
    
    @AfterReturning("pointcut()")
    public void afterReturning() {
        long s = System.currentTimeMillis();
 
        // ※栈顶弹出(后进先出)
        Stack> pairStack = THREAD_LOCAL.get();
        while (!pairStack.empty()) {
            Pair pair = pairStack.pop();
            pair.getKey().commit(pair.getValue());
        }
        THREAD_LOCAL.remove();
        long e = System.currentTimeMillis();
        log.info("afterReturning  消耗时间:{}  ms", (e - s));
    }
 
    
    @AfterThrowing(value = "pointcut()")
    public void afterThrowing() {
        long s = System.currentTimeMillis();
        // ※栈顶弹出(后进先出)
        Stack> pairStack = THREAD_LOCAL.get();
        while (!pairStack.empty()) {
            Pair pair = pairStack.pop();
            pair.getKey().rollback(pair.getValue());
        }
        THREAD_LOCAL.remove();
        long e = System.currentTimeMillis();
        log.info("afterThrowing  消耗时间:{}  ms", (e - s));
    }
}
三、使用教程

1、纯MySQL

@Transactional(rollbackFor = Exception.class)

2、纯MongoDB

@Transactional(value = "mongoTransactionManager", rollbackFor = Exception.class)

3、MySQL MongoDB混合

@MultiDataSourceTransactional
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/774718.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号