日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

java多数据源事务管理_Spring中实现多数据源事务管理 - CSDN博客

發布時間:2024/9/19 javascript 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java多数据源事务管理_Spring中实现多数据源事务管理 - CSDN博客 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

由于項目中引入了多個數據源,并且需要對多個數據源進行寫操作,那么多數據源的事務管理自然成了不可避免的問題,這也讓我對 @Transactional注解有了進一步的理解(但實際上也并不是非常深入)

然而這是一個演進的過程,剛開始項目中并沒有使用 @Transactional指定具體的 TransactionManager,所以新增一個數據源后,對原有的事務產生了影響了,這也是偶爾在一次測試報錯而結果沒有回滾之后才發現的,遂對于 @Transactional注解的一些參數項進行了了解。

研究

由于容器中存在兩個 TransactionManager,那么被 @Transactional注解的方法到底使用了哪個 TransactionManager來進行事務管理,抑或是同時使用了兩個 TransactionManager來進行事務管理都是我們需要搞清楚的問題。

首先我們先看看 @Transactional注解上有沒有提供配置項來指定 TransactionManager,果不其然,發現 value屬性就是用來指定具體 TransactionManager的,通過 id或者 name來指定唯一一個 TransactionManager,那么對于只需要一個事務管理的方法,問題就簡單多了: @Transactional(value = "database2TransactionManager")

public void test(String a) {

// business operation

}1

2

3

4

關于不指定TransactionManager時會使用哪一個TransactionManager,有興趣的童鞋可以參考另一篇文章,講的比較清晰: http://blog.sina.com.cn/s/blog_8f61307b0100ynfb.html

好了,回到我們研究的問題,那么對于需要寫入多個數據源的業務方法該怎么辦呢?

進一步研究

看來 @Transactional是沒有提供這種功能了,那么就自己寫了一個吧。我記得 Spring中的事務管理分編程式事務和聲明式事務。我們平時使用的 @Transactional就是聲明式事務,它的好處其實也就是靈活度更高、代碼的耦合性更低,最終的事務管理實現還是一樣的,只不過將具體邏輯都剝離到了切面中。所以我們可以手寫一個切面來寫一次“編程式事務”,當然在具體應用時,還是聲明式的。

Java中一般編程式事務的寫法: public class UserServiceImpl implements UserService {

@Resource

private TransactionManager txManager;

@Resource

private UserDao userDao;

@Resource

private AddressDao addressDao;

public boolean saveUser(User user) {

TransactionDefinition txDefinition = new TransactionDefinition();

TransactionStatus txStatus = txManager.getTransaction(txDefinition);

boolean result = false;

try {

result = userDao.save(user);

if(!result){

return false;

}

result = addressDao.save(user.getId(), user.getAddress());

txManager.commit(txStatus);

} catch (Exception e) {

result = false;

txManager.rollback(txStatus);

}

return result;

}

}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

我們借用這個邏輯將事務管理相關提取到切面中,并在進入目標方法之前,讓多個 TransactionManager都開啟事務,并在成功執行后一并提交或失敗后一并回滾,具體代碼: /**

* @author Zhu

* @date 2015-7-15

* @version 0.0.1

* @description

*/

public class MultiTransactionalAspect {

private Logger logger = LoggerFactory.getLogger(getClass());

public Object around(ProceedingJoinPoint pjp,

MultiTransactional multiTransactional) throws Throwable {

Stack dataSourceTransactionManagerStack = new Stack();

Stack transactionStatuStack = new Stack();

try {

if (!openTransaction(dataSourceTransactionManagerStack,

transactionStatuStack, multiTransactional)) {

return null;

}

Object ret = pjp.proceed();

commit(dataSourceTransactionManagerStack, transactionStatuStack);

return ret;

} catch (Throwable e) {

rollback(dataSourceTransactionManagerStack, transactionStatuStack);

logger.error(String.format(

"MultiTransactionalAspect, method:%s-%s occors error:", pjp

.getTarget().getClass().getSimpleName(), pjp

.getSignature().getName()), e);

throw e;

}

}

/**

* @author Zhu

* @date 2015-7-25下午7:55:46

* @description

* @param dataSourceTransactionManagerStack

* @param transactionStatuStack

* @param values

*/

private boolean openTransaction(

Stack dataSourceTransactionManagerStack,

Stack transactionStatuStack,

MultiTransactional multiTransactional) {

String[] transactionMangerNames = multiTransactional.values();

if (ArrayUtils.isEmpty(multiTransactional.values())) {

return false;

}

for (String beanName : transactionMangerNames) {

DataSourceTransactionManager dataSourceTransactionManager = (DataSourceTransactionManager) ContextHolder

.getBean(beanName);

TransactionStatus transactionStatus = dataSourceTransactionManager

.getTransaction(new DefaultTransactionDefinition());

transactionStatuStack.push(transactionStatus);

dataSourceTransactionManagerStack

.push(dataSourceTransactionManager);

}

return true;

}

/**

* @author Zhu

* @date 2015-7-25下午7:56:39

* @description

* @param dataSourceTransactionManagerStack

* @param transactionStatuStack

*/

private void commit(

Stack dataSourceTransactionManagerStack,

Stack transactionStatuStack) {

while (!dataSourceTransactionManagerStack.isEmpty()) {

dataSourceTransactionManagerStack.pop().commit(

transactionStatuStack.pop());

}

}

/**

* @author Zhu

* @date 2015-7-25下午7:56:42

* @description

* @param dataSourceTransactionManagerStack

* @param transactionStatuStack

*/

private void rollback(

Stack dataSourceTransactionManagerStack,

Stack transactionStatuStack) {

while (!dataSourceTransactionManagerStack.isEmpty()) {

dataSourceTransactionManagerStack.pop().rollback(

transactionStatuStack.pop());

}

}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

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

整體結構很清晰:

1. 首先根據指定的多個 TransactionManager依次開啟事務,這個次序不影響,因為其實大家都是平等的。

2. 其次就是調用目標方法執行具體的業務邏輯

3. 若是成功返回則提交每個事務,若中途報錯,那么就回滾每個事務

其中為什么要用 Stack來保存 TransactionManager和 TransactionStatus呢?那是因為 Spring的事務處理是按照 LIFO/stack behavior的方式進行的。如若順序有誤,則會報錯: java.lang.IllegalStateException: Cannot deactivate transaction synchronization - not active

at org.springframework.transaction.support.TransactionSynchronizationManager.clearSynchronization(TransactionSynchronizationManager.java:313)

at org.springframework.transaction.support.TransactionSynchronizationManager.clear(TransactionSynchronizationManager.java:451)

at org.springframework.transaction.support.AbstractPlatformTransactionManager.cleanupAfterCompletion(AbstractPlatformTransactionManager.java:986)

at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:782)

at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactio1

2

3

4

5

6

題外話

剛開始碰到這個問題的時候,先想到的是分布式事務管理,也去看了JTA相關的文章,但是好像比較麻煩,而且都是一些老文章,于是想試試自己實現,最后也實現了。所以想知道 JTA TransactionManager究竟有什么用呢?

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的java多数据源事务管理_Spring中实现多数据源事务管理 - CSDN博客的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。