一个项目中需要使用两个数据库,Oracle 和Mysql,于是参考各个blog,实现此功能。写好后才发现,原来的事务失效了,我去...
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 > <!-- 配置数据源: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" /> <!-- 连接池最大使用连接数量 --> < property name = "maxActive" value = "30" /> <!-- 连接池最小空闲 --> < property name = "minIdle" value = "2" /> <!-- 获取连接最大等待时间 --> < 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" /> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> < property name = "timeBetweenEvictionRunsMillis" value = "10000" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> < property name = "minEvictableIdleTimeMillis" value = "30000" /> <!-- 打开removeAbandoned功能 --> < property name = "removeAbandoned" value = "true" /> <!-- 1800秒,也就是30分钟 --> < property name = "removeAbandonedTimeout" value = "1800" /> <!-- 关闭abanded连接时输出错误日志 --> < property name = "logAbandoned" value = "true" /> <!-- 监控数据库 --> < 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 > <!-- 配置数据库注解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" /> <!--数据源选择切面,保证在事务开始之前执行--> < aop:advisor pointcut-ref = "transactionPointcut" advice-ref = "dataSourceAspect" order = "1" /> </ aop:config > |
注解切换,默认使用oracle数据源
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"; } |
注解方式实现切换数据源,搜索注释,更换注释上面的数据源,支持类注释和方法注释
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 { //首先取类上的数据源 if(method.getDeclaringClass().isAnnotationPresent(DataSource.class) && !method.isAnnotationPresent(DataSource.class)) { DataSource datasource = method.getDeclaringClass().getAnnotation(DataSource.class); MultipleDataSource.setDataSource(datasource.name()); //方法上的数据源 优先级高于类上的 } else if (method.isAnnotationPresent(DataSource.class)) { DataSource datasource = method.getAnnotation(DataSource.class); MultipleDataSource.setDataSource(datasource.name()); } else { MultipleDataSource.setDataSource(DataSource.oracleDataSource); } } } |
继承AbstractRoutingDataSource实现数据源切换
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); } //清除数据源 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 多数据源切换,不支持事务控制的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:http://www.cnblogs.com/eastday/archive/2017/09/28/7608455.html