真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

詳解基于spring多數(shù)據(jù)源動(dòng)態(tài)調(diào)用及其事務(wù)處理

需求:

成都創(chuàng)新互聯(lián)公司于2013年創(chuàng)立,先為貴池等服務(wù)建站,貴池等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為貴池企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。

有些時(shí)候,我們需要連接多個(gè)數(shù)據(jù)庫,但是,在方法調(diào)用前并不知道到底是調(diào)用哪個(gè)。即同時(shí)保持多個(gè)數(shù)據(jù)庫的連接,在方法中根據(jù)傳入的參數(shù)來確定。

下圖的單數(shù)據(jù)源的調(diào)用和多數(shù)據(jù)源動(dòng)態(tài)調(diào)用的流程,可以看出在Dao層中需要有一個(gè)DataSource選擇器,來確定到底是調(diào)用哪個(gè)數(shù)據(jù)源。

詳解基于spring多數(shù)據(jù)源動(dòng)態(tài)調(diào)用及其事務(wù)處理

實(shí)現(xiàn)方式

對(duì)Dao層提供一個(gè)公共父類,保持有多個(gè)數(shù)據(jù)源的連接(本人是基于iBatis,即保持多個(gè)SQLSessionTemplate)

/**

 * Created by hzlizhou on 2017/2/6.

 */

public abstract class MultiDatasourceDao implements IDaoSupport {

 

  private Map sqlSessionTemplateMap;

 

  private MultiDataSourceSelector multiDataSourceSelector;

 

  public MultiDatasourceDao(Map sqlSessionTemplateMap, MultiDataSourceSelector multiDataSourceSelector) {

    this.sqlSessionTemplateMap = sqlSessionTemplateMap;

    this.multiDataSourceSelector = multiDataSourceSelector;

  }

 

  public Map getSqlSessionTemplateMap() {

    return sqlSessionTemplateMap;

  }

 

  public void setSqlSessionTemplateMap(Map sqlSessionTemplateMap) {

    this.sqlSessionTemplateMap = sqlSessionTemplateMap;

  }

 

  //子類通過這個(gè)方法動(dòng)態(tài)獲取SqlSessionTemplate

  protected SqlSessionTemplate getSqlSessionTemplate() {

    String clusterName = multiDataSourceSelector.getName();

    SqlSessionTemplate result = sqlSessionTemplateMap.get(clusterName);

    Assert.notNull(result);

    return result;

  }

}  

MultiDataSourceSelector是一個(gè)借口,根據(jù)當(dāng)前的調(diào)用環(huán)境,返回不不同的參數(shù),根據(jù)這個(gè)參數(shù)就可以確定使用哪一個(gè)SQLSessionTemplate,例如我是把當(dāng)前環(huán)境放入到ThreadLocal中的

public interface MultiDataSourceSelector {

  String getName();

}

public class DubboContextDataSourceSelector implements MultiDataSourceSelector {

 

  private String defaultName;

 

  public DubboContextDataSourceSelector(String defaultName) {

    this.defaultName = defaultName;

  }

 

  @Override

  public String getName() {

    //DubboContextHolder 是一個(gè)保持一個(gè)ThreadLocal的Map

    String res = DubboContextHolder.getContext().get(DubboContextConstants.CLUSTER_NAME);

    if (res == null) {

      res = getDefaultName();

    }

    return res;

  }

 

  public String getDefaultName() {

    return defaultName;

  }

} 

然后在Dao層的中獲取SQLSessionTemplate的時(shí)候就是動(dòng)態(tài)了。

動(dòng)態(tài)事務(wù)

其實(shí)這個(gè)都好辦,然后我們就面臨一個(gè)稍微復(fù)雜一點(diǎn)的問題,那DataSource是動(dòng)態(tài)的,事務(wù)也就必須是動(dòng)態(tài)了的。而且還對(duì)原有的代碼沒有侵入(例如Spring中的@Transactional 注解),那實(shí)現(xiàn)一個(gè)類似@Transactional的方法吧。名字就叫做@DynamicTransactional

@Documented

@Target({METHOD, TYPE})

@Retention(RUNTIME)

public @interface DynamicTransactional {

 

  Propagation propagation() default Propagation.REQUIRED;

 

  Class<? extends Throwable>[] rollbackFor() default {};

} 

基本思想是在通過AOP切面攔截@DynamicTransactional注解,調(diào)用,然后自己編程實(shí)現(xiàn)事務(wù)

詳解基于spring多數(shù)據(jù)源動(dòng)態(tài)調(diào)用及其事務(wù)處理

切面內(nèi)的核心方法是

private Object invokeWithinTransaction(final ProceedingJoinPoint pjp, final DynamicTransactional dynamicTransaction) {

 

  //創(chuàng)建TransactionTemplate

  final PlatformTransactionManager tran = multiTransactionManagerHolder.getTransactionManager();

  TransactionTemplate transactionTemplate = new TransactionTemplate();

  transactionTemplate.setPropagationBehavior(dynamicTransaction.propagation().value());

  transactionTemplate.setTransactionManager(tran);

 

  //在事務(wù)中執(zhí)行

  return transactionTemplate.execute(new TransactionCallback() {

    @Override

    public Object doInTransaction(TransactionStatus status) {

      Object result = null;

      try {

        result = pjp.proceed();

      } catch (Throwable throwable) {

        Class<? extends Throwable>[] c = dynamicTransaction.rollbackFor();

        for (Class<? extends Throwable> tmp : c) {

          if (tmp.isAssignableFrom(throwable.getClass())) {

            status.setRollbackOnly();

          }

        }

      }

      return result;

    }

  });

} 

其中multiTransactionManagerHolder和上面動(dòng)態(tài)數(shù)據(jù)源選擇的原理一樣,通過從ThreadLocal中拿去變量,選擇對(duì)應(yīng)的TransactionManager返回

 切面的配置:重點(diǎn)是怎么對(duì)指定注解進(jìn)行切面



  

    

  


當(dāng)然,這里只是實(shí)現(xiàn)了在方法上的@DynamicTransactional使用,如果該注解還要對(duì)類使用,對(duì)所有函數(shù)加一個(gè)切點(diǎn),判斷該切點(diǎn)的類上是否有@DynamicTransactional注解

注意:由于切面的優(yōu)先級(jí),如果要實(shí)現(xiàn) 方法上的注解優(yōu)先級(jí)高于類上的,還需要一點(diǎn)點(diǎn)小的處理

調(diào)用時(shí)序圖

自己實(shí)現(xiàn)基于AbstractRoutingDataSource,把多個(gè)DataSource加入到SQLSessionFactory,和之前的方式一樣,通過ThreadLocal來確定使用哪個(gè)DataSource。

詳解基于spring多數(shù)據(jù)源動(dòng)態(tài)調(diào)用及其事務(wù)處理

關(guān)于動(dòng)態(tài)事務(wù),上面是使用切面,自定義標(biāo)簽,使用TransactionTemplate來實(shí)現(xiàn)的,如果想更優(yōu)雅的話,可以仿照DataSourceTransactionManager寫一個(gè),

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。


分享標(biāo)題:詳解基于spring多數(shù)據(jù)源動(dòng)態(tài)調(diào)用及其事務(wù)處理
文章轉(zhuǎn)載:http://weahome.cn/article/jcddie.html

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部