一個(gè)項(xiàng)目中需要使用兩個(gè)數(shù)據(jù)庫,Oracle 和Mysql,于是參考各個(gè)blog,實(shí)現(xiàn)此功能。寫好后才發(fā)現(xiàn),原來的事務(wù)失效了,我去...
spring-mybatis.xml 配置
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
102
103
104
105
106
107
108
109
110
111
112
|
< bean id = "configReader" class = "org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer" > < property name = "locations" > < list > < value >classpath:spring/db.properties</ value > </ list > </ property > < property name = "ignoreResourceNotFound" value = "true" /> </ bean > < bean id = "dataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource" > < property name = "driverClass" value = "${jdbc.oracle.DriverClassName}" ></ property > < property name = "jdbcUrl" value = "${jdbc.oracle.Url}" ></ property > < property name = "user" value = "${jdbc.oracle.UserName}" ></ property > < property name = "password" value = "${jdbc.oracle.UserPassword}" ></ property > < property name = "acquireIncrement" value = "5" ></ property > < property name = "initialPoolSize" value = "5" ></ property > < property name = "maxIdleTime" value = "60" ></ property > < property name = "maxPoolSize" value = "100" ></ property > < property name = "minPoolSize" value = "5" ></ property > </ bean > <!-- 配置數(shù)據(jù)源:MySQL start --> < bean name = "mySqlDataSource" class = "com.alibaba.druid.pool.DruidDataSource" init-method = "init" destroy-method = "close" > < property name = "driverClassName" value = "${jdbc.mysql.DriverClassName}" /> < property name = "url" value = "${jdbc.mysql.Url}" /> < property name = "username" value = "${jdbc.mysql.UserName}" /> < property name = "password" value = "${jdbc.mysql.UserPassword}" /> <!-- 初始化連接大小 --> < property name = "initialSize" value = "5" /> <!-- 連接池最大使用連接數(shù)量 --> < property name = "maxActive" value = "30" /> <!-- 連接池最小空閑 --> < property name = "minIdle" value = "2" /> <!-- 獲取連接最大等待時(shí)間 --> < property name = "maxWait" value = "300" /> < property name = "validationQuery" value = "SELECT 1" /> < property name = "testOnBorrow" value = "false" /> < property name = "testOnReturn" value = "false" /> < property name = "testWhileIdle" value = "true" /> <!-- 配置間隔多久才進(jìn)行一次檢測(cè),檢測(cè)需要關(guān)閉的空閑連接,單位是毫秒 --> < property name = "timeBetweenEvictionRunsMillis" value = "10000" /> <!-- 配置一個(gè)連接在池中最小生存的時(shí)間,單位是毫秒 --> < property name = "minEvictableIdleTimeMillis" value = "30000" /> <!-- 打開removeAbandoned功能 --> < property name = "removeAbandoned" value = "true" /> <!-- 1800秒,也就是30分鐘 --> < property name = "removeAbandonedTimeout" value = "1800" /> <!-- 關(guān)閉abanded連接時(shí)輸出錯(cuò)誤日志 --> < property name = "logAbandoned" value = "true" /> <!-- 監(jiān)控?cái)?shù)據(jù)庫 --> < property name = "filters" value = "stat" /> </ bean > < bean id = "multipleDataSource" class = "com.we.database.MultipleDataSource" > < property name = "defaultTargetDataSource" ref = "dataSource" /> < property name = "targetDataSources" > < map > < entry key = "oracleDataSource" value-ref = "dataSource" /> < entry key = "mySqlDataSource" value-ref = "mySqlDataSource" /> </ map > </ property > </ bean > <!-- oracle myBatis file --> < bean id = "sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean" > < property name = "dataSource" ref = "multipleDataSource" /> <!--<property name="configLocation" value="classpath:configuration.xml" /> --> < property name = "mapperLocations" value = "classpath:com/we/dao/mapper/*.xml" /> </ bean > < bean class = "org.mybatis.spring.mapper.MapperScannerConfigurer" > < property name = "basePackage" value = "com.we.dao" /> < property name = "sqlSessionFactoryBeanName" value = "sqlSessionFactory" /> </ bean > <!-- configure transaction --> < bean id = "transactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" > < property name = "dataSource" ref = "dataSource" /> </ bean > <!-- annotation transaction --> < tx:annotation-driven transaction-manager = "transactionManager" proxy-target-class = "true" /> <!-- interception transatcion --> < tx:advice id = "transactionAdvice" transaction-manager = "transactionManager" > < tx:attributes > < tx:method name = "add*" propagation = "REQUIRED" /> </ tx:attributes > </ tx:advice > <!-- 配置數(shù)據(jù)庫注解aop --> < bean id = "dataSourceAspect" class = "com.we.database.DataSourceAspect" /> < aop:config > < aop:pointcut id = "transactionPointcut" expression = "execution(* com.wewe.licai.service..*Impl.*(..))" /> < aop:advisor pointcut-ref = "transactionPointcut" advice-ref = "transactionAdvice" order = "2" /> <!--數(shù)據(jù)源選擇切面,保證在事務(wù)開始之前執(zhí)行--> < aop:advisor pointcut-ref = "transactionPointcut" advice-ref = "dataSourceAspect" order = "1" /> </ aop:config > |
注解切換,默認(rèn)使用oracle數(shù)據(jù)源
1
2
3
4
5
6
7
8
9
|
@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD,ElementType.TYPE}) public @interface DataSource { String name() default DataSource.oracleDataSource; String mySqlDataSource = "mySqlDataSource"; String oracleDataSource = "oracleDataSource"; } |
注解方式實(shí)現(xiàn)切換數(shù)據(jù)源,搜索注釋,更換注釋上面的數(shù)據(jù)源,支持類注釋和方法注釋
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
|
/** * Created by eastday on 2017/9/21. */ public class DataSourceAspect implements MethodBeforeAdvice,AfterReturningAdvice { @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { MultipleDataSource.clearDataSource(); } @Override public void before(Method method, Object[] args, Object target) throws Throwable { //首先取類上的數(shù)據(jù)源 if(method.getDeclaringClass().isAnnotationPresent(DataSource.class) && !method.isAnnotationPresent(DataSource.class)) { DataSource datasource = method.getDeclaringClass().getAnnotation(DataSource.class); MultipleDataSource.setDataSource(datasource.name()); //方法上的數(shù)據(jù)源 優(yōu)先級(jí)高于類上的 } else if (method.isAnnotationPresent(DataSource.class)) { DataSource datasource = method.getAnnotation(DataSource.class); MultipleDataSource.setDataSource(datasource.name()); } else { MultipleDataSource.setDataSource(DataSource.oracleDataSource); } } } |
繼承AbstractRoutingDataSource實(shí)現(xiàn)數(shù)據(jù)源切換
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class MultipleDataSource extends AbstractRoutingDataSource { private static final ThreadLocal< String > dataSources = new InheritableThreadLocal< String >(); public static void setDataSource(String dataSource) { dataSources.set(dataSource); } //清除數(shù)據(jù)源 public static void clearDataSource() { dataSources.remove(); } @Override protected Object determineCurrentLookupKey() { return dataSources.get(); } } |
使用demo
1
2
3
4
5
6
7
8
9
10
11
|
@DataSource(name = DataSource.mySqlDataSource) public class ContentServiceImpl implements IContentService { @Autowired private IContentDao contentDao; @Override public Content queryOne(String type) { return contentDao.queryOne(type); } } |
以上這篇解決spring mvc 多數(shù)據(jù)源切換,不支持事務(wù)控制的問題就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://www.cnblogs.com/eastday/archive/2017/09/28/7608455.html