详解基于春天多数据源动态调用及其事务处理

  

<强>需求:

  

有些时候,我们需要连接多个数据库,但是,在方法调用前并不知道到底是调用哪个。即同时保持多个数据库的连接,在方法中根据传入的参数来确定。

  

下图的单数据源的调用和多数据源动态调用的流程,可以看出在Dao层中需要有一个数据源选择器,来确定到底是调用哪个数据源。

  

详解基于春天多数据源动态调用及其事务处理

  

<>强实现方式

  

对Dao层提供一个公共父类,保持有多个数据源的连接(本人是基于iBatis,即保持多个SQLSessionTemplate)

     /* *      *由hzlizhou>   公共接口MultiDataSourceSelector {      字符串getName ();      }      公共类DubboContextDataSourceSelector实现MultiDataSourceSelector {            私人字符串defaultName;            公共DubboContextDataSourceSelector(字符串defaultName) {      this.defaultName=defaultName;      }            @Override      公共字符串getName () {//DubboContextHolder是一个保持一个ThreadLocal的地图      字符串res=DubboContextHolder.getContext () . get (DubboContextConstants.CLUSTER_NAME);      如果(res==null) {      res=getDefaultName ();      }      返回res;      }            公共字符串getDefaultName () {      返回defaultName;      }      }      之前      

然后在Dao层的中获取SQLSessionTemplate的时候就是动态了。

  

<强>动态事务

  

其实这个都好办,然后我们就面临一个稍微复杂一点的问题,那数据源是动态的,事务也就必须是动态了的,而且还对原有的代码没有侵入(例如春天中的@ transactional注解),那实现一个类似@ transactional的方法吧。名字就叫做@DynamicTransactional

        @Documented      @Target({方法,类型})      @Retention(运行时)      公共@ interface DynamicTransactional {            传播传播()缺省Propagation.REQUIRED;            Class<& # 63;扩展Throwable> [] rollbackFor违约(){};      }      之前      

基本思想是在通过AOP切面拦截@DynamicTransactional注解,调用,然后自己编程实现事务

  

详解基于春天多数据源动态调用及其事务处理

  

切面内的核心方法是

        私有对象invokeWithinTransaction(最终ProceedingJoinPoint pjp、最终DynamicTransactional dynamicTransaction) {//创建TransactionTemplate      最后PlatformTransactionManager tran=multiTransactionManagerHolder.getTransactionManager ();      TransactionTemplate TransactionTemplate=new TransactionTemplate ();      transactionTemplate.setPropagationBehavior (dynamicTransaction.propagation () value ());      transactionTemplate.setTransactionManager (tran);//在事务中执行      transactionTemplate返回。执行(新的TransactionCallback () {      @Override      公共对象doInTransaction (TransactionStatus状态){      对象的结果=零;      尝试{      结果=pjp.proceed ();      }捕捉(Throwable Throwable) {      Class<& # 63;扩展Throwable> [] c=dynamicTransaction.rollbackFor ();      (Class<& # 63;Throwable>延伸;tmp: c) {      如果(tmp.isAssignableFrom (throwable.getClass ())) {      status.setRollbackOnly ();      }      }      }      返回结果;      }      });      }      之前      

其中multiTransactionManagerHolder和上面动态数据源选择的原理一样,通过从ThreadLocal中拿去变量,选择对应的TransactionManager返回

  

,切面的配置:重点是怎么对指定注解进行切面

        & lt; aop: config>      & lt; aop: id=癿ultiTransactionManagerAspect”方面ref=癿ultiTransactionManagerAop”比;      & lt; aop:在方法=" invokeWithinTransaction "      arg-names=" dynamicTransaction "      切入点=" @annotation (dynamicTransaction)”/比;      & lt;/aop: aspect>      & lt;/aop: config>   之前      

当然,这里只是实现了在方法上的@DynamicTransactional使用,如果该注解还要对类使用,对所有函数加一个切点,判断该切点的类上是否有@DynamicTransactional注解

详解基于春天多数据源动态调用及其事务处理

Copyright © 2020-2023 feiqueyun.cn. All Rights Reserved. 肥雀云_南京肥雀信息技术有限公司版权所有 南京肥雀信息技术有限公司 苏ICP备16063723号-5