一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 詳解基于spring多數據源動態調用及其事務處理

詳解基于spring多數據源動態調用及其事務處理

2020-11-25 10:47atheva Java教程

本篇文章主要介紹了基于spring多數據源動態調用及其事務處理 ,具有一定的參考價值,感興趣的小伙伴們可以參考一下

需求:

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

下圖的單數據源的調用和多數據源動態調用的流程,可以看出在dao層中需要有一個datasource選擇器,來確定到底是調用哪個數據源。

詳解基于spring多數據源動態調用及其事務處理

實現方式

對dao層提供一個公共父類,保持有多個數據源的連接(本人是基于ibatis,即保持多個sqlsessiontemplate)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
 
 * 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;
 
  }
 
 
 
  //子類通過這個方法動態獲取sqlsessiontemplate
 
  protected sqlsessiontemplate getsqlsessiontemplate() {
 
    string clustername = multidatasourceselector.getname();
 
    sqlsessiontemplate result = sqlsessiontemplatemap.get(clustername);
 
    assert.notnull(result);
 
    return result;
 
  }
 
} 

multidatasourceselector是一個借口,根據當前的調用環境,返回不不同的參數,根據這個參數就可以確定使用哪一個sqlsessiontemplate,例如我是把當前環境放入到threadlocal中的

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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的時候就是動態了。

動態事務

其實這個都好辦,然后我們就面臨一個稍微復雜一點的問題,那datasource是動態的,事務也就必須是動態了的。而且還對原有的代碼沒有侵入(例如spring中的@transactional 注解),那實現一個類似@transactional的方法吧。名字就叫做@dynamictransactional

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@documented
 
@target({method, type})
 
@retention(runtime)
 
public @interface dynamictransactional {
 
 
 
  propagation propagation() default propagation.required;
 
 
 
  class<? extends throwable>[] rollbackfor() default {};
 
}

基本思想是在通過aop切面攔截@dynamictransactional注解,調用,然后自己編程實現事務

詳解基于spring多數據源動態調用及其事務處理

切面內的核心方法是

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
private object invokewithintransaction(final proceedingjoinpoint pjp, final dynamictransactional dynamictransaction) {
 
 
 
  //創建transactiontemplate
 
  final platformtransactionmanager tran = multitransactionmanagerholder.gettransactionmanager();
 
  transactiontemplate transactiontemplate = new transactiontemplate();
 
  transactiontemplate.setpropagationbehavior(dynamictransaction.propagation().value());
 
  transactiontemplate.settransactionmanager(tran);
 
 
 
  //在事務中執行
 
  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和上面動態數據源選擇的原理一樣,通過從threadlocal中拿去變量,選擇對應的transactionmanager返回

 切面的配置:重點是怎么對指定注解進行切面

?
1
2
3
4
5
6
7
8
9
10
11
12
13
<aop:config>
 
  <aop:aspect id="multitransactionmanageraspect" ref="multitransactionmanageraop">
 
    <aop:around method="invokewithintransaction"
 
               arg-names="dynamictransaction"
 
               pointcut="@annotation(dynamictransaction)"/>
 
  </aop:aspect>
 
</aop:config>

當然,這里只是實現了在方法上的@dynamictransactional使用,如果該注解還要對類使用,對所有函數加一個切點,判斷該切點的類上是否有@dynamictransactional注解

注意:由于切面的優先級,如果要實現 方法上的注解優先級高于類上的,還需要一點點小的處理

調用時序圖

自己實現基于abstractroutingdatasource,把多個datasource加入到sqlsessionfactory,和之前的方式一樣,通過threadlocal來確定使用哪個datasource。

詳解基于spring多數據源動態調用及其事務處理

關于動態事務,上面是使用切面,自定義標簽,使用transactiontemplate來實現的,如果想更優雅的話,可以仿照datasourcetransactionmanager寫一個,

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/lizo/p/7089263.html?utm_source=tuicool&utm_medium=referral

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 不良研究所地址一 | 亚洲入口 | 青草青青在线视频 | 波多野结衣之双方调教在线观看 | 美女在线看永久免费网址 | 无限时间看片在线观看 | 日本sss在线高清观看 | 99视频精品国在线视频艾草 | 国产三及 | 日本欧美不卡一区二区三区在线 | 91九色porny国产美女一区 | 亚洲精品久久久久久婷婷 | 午夜国产精品视频 | 欧美图片小说 | 国产午夜精品福利久久 | 久久91精品国产91久 | 99国产精品免费视频 | ai换脸杨颖啪啪免费网站 | 99精品视频在线观看免费 | 亚洲精品动漫免费二区 | 四虎精品永久免费 | 欧美伊香蕉久久综合类网站 | 国产成人精品免费视频大全五级 | 久久99热在线观看7 久久99精品涩AV毛片观看 | 69热精品视频在线看影院 | 国产一区二区三区四区波多野结衣 | 国产精品久久久久久搜索 | 高清在线观看免费入口 | 91高跟丝袜 | 美日韩在线观看 | 免费视频精品一区二区 | 成年视频在线观看免费 | 日韩一区二区三区在线 | 亚洲四虎| 亚洲精品国产专区91在线 | www视频在线免费观看 | 国色天香社区在线视频播放 | 星空无限传媒xk8129 | 久久99国产精品二区不卡 | 四虎影视在线观看永久地址 | 婷婷久久精品 |