最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2017年06月28日 14:38:51   作者:atheva  
本篇文章主要介紹了基于spring多數(shù)據(jù)源動態(tài)調(diào)用及其事務(wù)處理 ,具有一定的參考價值,感興趣的小伙伴們可以參考一下

需求:

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

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

實現(xiàn)方式

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

/**

 * Created by hzlizhou on 2017/2/6.

 */

public abstract class MultiDatasourceDao implements IDaoSupport {

 

  private Map<String, SqlSessionTemplate> sqlSessionTemplateMap;

 

  private MultiDataSourceSelector multiDataSourceSelector;

 

  public MultiDatasourceDao(Map<String, SqlSessionTemplate> sqlSessionTemplateMap, MultiDataSourceSelector multiDataSourceSelector) {

    this.sqlSessionTemplateMap = sqlSessionTemplateMap;

    this.multiDataSourceSelector = multiDataSourceSelector;

  }

 

  public Map<String, SqlSessionTemplate> getSqlSessionTemplateMap() {

    return sqlSessionTemplateMap;

  }

 

  public void setSqlSessionTemplateMap(Map<String, SqlSessionTemplate> sqlSessionTemplateMap) {

    this.sqlSessionTemplateMap = sqlSessionTemplateMap;

  }

 

  //子類通過這個方法動態(tài)獲取SqlSessionTemplate

  protected SqlSessionTemplate getSqlSessionTemplate() {

    String clusterName = multiDataSourceSelector.getName();

    SqlSessionTemplate result = sqlSessionTemplateMap.get(clusterName);

    Assert.notNull(result);

    return result;

  }

}  

MultiDataSourceSelector是一個借口,根據(jù)當(dāng)前的調(diào)用環(huán)境,返回不不同的參數(shù),根據(jù)這個參數(shù)就可以確定使用哪一個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 是一個保持一個ThreadLocal的Map

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

    if (res == null) {

      res = getDefaultName();

    }

    return res;

  }

 

  public String getDefaultName() {

    return defaultName;

  }

} 

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

動態(tài)事務(wù)

其實這個都好辦,然后我們就面臨一個稍微復(fù)雜一點的問題,那DataSource是動態(tài)的,事務(wù)也就必須是動態(tài)了的。而且還對原有的代碼沒有侵入(例如Spring中的@Transactional 注解),那實現(xiàn)一個類似@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)用,然后自己編程實現(xiàn)事務(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<Object>() {

    @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和上面動態(tài)數(shù)據(jù)源選擇的原理一樣,通過從ThreadLocal中拿去變量,選擇對應(yīng)的TransactionManager返回

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

<aop:config>

  <aop:aspect id="multiTransactionManagerAspect" ref="multiTransactionManagerAop">

    <aop:around method="invokeWithinTransaction"

               arg-names="dynamicTransaction"

               pointcut="@annotation(dynamicTransaction)"/>

  </aop:aspect>

</aop:config>

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

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

調(diào)用時序圖

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

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

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 通過自定制LogManager實現(xiàn)程序完全自定義的logger

    通過自定制LogManager實現(xiàn)程序完全自定義的logger

    本章主要闡述怎么完全定制化LogManager來實現(xiàn)應(yīng)用程序完全自定制的logger,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • springmvc集成shiro登錄失敗處理操作

    springmvc集成shiro登錄失敗處理操作

    這篇文章主要介紹了springmvc集成shiro登錄失敗處理操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • java 漢諾塔詳解及實現(xiàn)代碼

    java 漢諾塔詳解及實現(xiàn)代碼

    這篇文章主要介紹了java 漢諾塔詳解及實現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Java后臺實現(xiàn)微信支付和微信退款

    Java后臺實現(xiàn)微信支付和微信退款

    這篇文章主要介紹了Java后臺實現(xiàn)微信支付和微信退款,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Spring Security單項目權(quán)限設(shè)計過程解析

    Spring Security單項目權(quán)限設(shè)計過程解析

    這篇文章主要介紹了Spring Security單項目權(quán)限設(shè)計過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Java基礎(chǔ)-Java編程語言發(fā)展史

    Java基礎(chǔ)-Java編程語言發(fā)展史

    這篇文章主要介紹了Java基礎(chǔ)-Java編程語言發(fā)展簡史,Java源自Sun公司的一個叫Green的項目,其原先的目的是為家用電子消費產(chǎn)品開發(fā)一個分布式代碼系統(tǒng),這樣就可以將通信和控制信息發(fā)給電冰箱、電視機(jī)、烤面包機(jī)等家用電器,對它們進(jìn)行控制和信息交流,需要的朋友可以參考一下
    2022-01-01
  • SpringBoot+Spring Security基于內(nèi)存用戶認(rèn)證的實現(xiàn)

    SpringBoot+Spring Security基于內(nèi)存用戶認(rèn)證的實現(xiàn)

    本文介紹了SpringBoot+Spring Security基于內(nèi)存用戶認(rèn)證的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-11-11
  • Java觀察者設(shè)計模式(Observable和Observer)

    Java觀察者設(shè)計模式(Observable和Observer)

    這篇文章主要介紹了 Java觀察者設(shè)計模式(Observable和Observer)的相關(guān)資料,需要的朋友可以參考下
    2015-12-12
  • 詳解Java編程中線程同步以及定時啟動線程的方法

    詳解Java編程中線程同步以及定時啟動線程的方法

    這篇文章主要介紹了詳解Java編程中線程同步以及定時啟動線程的方法, 講到了wait()與notify()方法以及阻塞隊列等知識,需要的朋友可以參考下
    2016-01-01
  • Java接口的作用以及使用說明

    Java接口的作用以及使用說明

    接口是一種規(guī)范,定義了一組方法的原型,但沒有實現(xiàn),類通過實現(xiàn)接口來實現(xiàn)接口中的抽象方法,接口可以提供規(guī)范性、擴(kuò)展性和可插入性,在Java中,接口可以用來聲明一個變量,實現(xiàn)接口的類必須實現(xiàn)接口中定義的所有方法,接口提供了一種機(jī)制
    2024-11-11

最新評論

怀化市| 宜兴市| 萨嘎县| 克什克腾旗| 海丰县| 赤城县| 佛冈县| 万盛区| 容城县| 同仁县| 云霄县| 乌鲁木齐县| 独山县| 丽水市| 江川县| 金溪县| 万宁市| 新民市| 三门县| 嘉善县| 乐安县| 胶州市| 马山县| 白朗县| 东海县| 盐津县| 义马市| 绥化市| 巴彦县| 湖南省| 府谷县| 田阳县| 连江县| 安泽县| 鲁甸县| 酒泉市| 四川省| 文昌市| 青浦区| 洪洞县| 张掖市|