一个项目中需要使用两个数据库,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