7
7
- [ druid] ( https://github.com/helloworlde/SpringBoot-DynamicDataSource/tree/druid ) : 通过切面和注解方式实现的使用 Druid 连接池的动态数据源切换
8
8
- [ aspect_dao] ( https://github.com/helloworlde/SpringBoot-DynamicDataSource/tree/aspect_dao ) : 通过切面实现的 DAO 层的动态数据源切换
9
9
- [ roundrobin] ( https://github.com/helloworlde/SpringBoot-DynamicDataSource/tree/roundrobin ) : 通过切面使用轮询方式实现的只读数据源负载均衡
10
- - [ hikari] ( https://github.com/helloworlde/SpringBoot-DynamicDataSource/tree/hikari ) : 升级到SpringBoot 2.0, 数据源使用 Hikari
10
+ - [ hikari] ( https://github.com/helloworlde/SpringBoot-DynamicDataSource/tree/hikari ) : 升级到SpringBoot 2.0版本 数据源使用 Hikar
11
+ - ** [ 多数据源分布式事务] ( https://github.com/helloworlde/spring-cloud-alibaba-component/tree/master/cloud-seata-multi-datasource ) : 使用 [ Seata] ( https://github.com/seata/seata ) 实现的多数据源事务**
12
+
11
13
12
14
> 以上分支都是基于 dev 分支修改或扩充而来,基本涵盖了常用的多数据源动态切换的方式,基本的原理都一样,都是通过切面根据不同的条件在执行数据库操作前切换数据源
13
15
29
31
## 添加依赖
30
32
``` groovy
31
33
dependencies {
32
- compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1 ')
34
+ compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.2 ')
33
35
compile('org.springframework.boot:spring-boot-starter-web')
34
36
compile('org.springframework.boot:spring-boot-starter-aop')
35
- compile('com.alibaba:druid-spring-boot-starter:1.1.6')
36
37
runtime('mysql:mysql-connector-java')
37
38
testCompile('org.springframework.boot:spring-boot-starter-test')
38
39
}
@@ -84,88 +85,40 @@ INSERT INTO product_slave_gamma.product (name, price) VALUES('slaveGamma', '1');
84
85
- application.properties
85
86
86
87
``` properties
88
+ spring.datasource.type =com.zaxxer.hikari.HikariDataSource
87
89
# Master datasource config
88
- spring.datasource.druid .master.name =master
89
- spring.datasource.druid .master.driver-class-name =com.mysql.jdbc.Driver
90
- spring.datasource.druid .master.url =jdbc:mysql://localhost/product_master?useSSL =false
91
- spring.datasource.druid .master.port =3306
92
- spring.datasource.druid .master.username =root
93
- spring.datasource.druid .master.password =123456
90
+ spring.datasource.hikari .master.name =master
91
+ spring.datasource.hikari .master.driver-class-name =com.mysql.jdbc.Driver
92
+ spring.datasource.hikari .master.jdbc- url =jdbc:mysql://localhost/product_master?useSSL =false
93
+ spring.datasource.hikari .master.port =3306
94
+ spring.datasource.hikari .master.username =root
95
+ spring.datasource.hikari .master.password =123456
94
96
95
97
# SlaveAlpha datasource config
96
- spring.datasource.druid .slave-alpha.name =SlaveAlpha
97
- spring.datasource.druid .slave-alpha.driver-class-name =com.mysql.jdbc.Driver
98
- spring.datasource.druid .slave-alpha.url =jdbc:mysql://localhost/product_slave_alpha?useSSL =false
99
- spring.datasource.druid .slave-alpha.port =3306
100
- spring.datasource.druid .slave-alpha.username =root
101
- spring.datasource.druid .slave-alpha.password =123456
98
+ spring.datasource.hikari .slave-alpha.name =SlaveAlpha
99
+ spring.datasource.hikari .slave-alpha.driver-class-name =com.mysql.jdbc.Driver
100
+ spring.datasource.hikari .slave-alpha.jdbc- url =jdbc:mysql://localhost/product_slave_alpha?useSSL =false
101
+ spring.datasource.hikari .slave-alpha.port =3306
102
+ spring.datasource.hikari .slave-alpha.username =root
103
+ spring.datasource.hikari .slave-alpha.password =123456
102
104
103
105
# SlaveBeta datasource config
104
- spring.datasource.druid .slave-beta.name =SlaveBeta
105
- spring.datasource.druid .slave-beta.driver-class-name =com.mysql.jdbc.Driver
106
- spring.datasource.druid .slave-beta.url =jdbc:mysql://localhost/product_slave_beta?useSSL =false
107
- spring.datasource.druid .slave-beta.port =3306
108
- spring.datasource.druid .slave-beta.username =root
109
- spring.datasource.druid .slave-beta.password =123456
106
+ spring.datasource.hikari .slave-beta.name =SlaveBeta
107
+ spring.datasource.hikari .slave-beta.driver-class-name =com.mysql.jdbc.Driver
108
+ spring.datasource.hikari .slave-beta.jdbc- url =jdbc:mysql://localhost/product_slave_beta?useSSL =false
109
+ spring.datasource.hikari .slave-beta.port =3306
110
+ spring.datasource.hikari .slave-beta.username =root
111
+ spring.datasource.hikari .slave-beta.password =123456
110
112
111
113
# SlaveGamma datasource config
112
- spring.datasource.druid.slave-gamma.name =SlaveGamma
113
- spring.datasource.druid.slave-gamma.driver-class-name =com.mysql.jdbc.Driver
114
- spring.datasource.druid.slave-gamma.url =jdbc:mysql://localhost/product_slave_gamma?useSSL =false
115
- spring.datasource.druid.slave-gamma.port =3306
116
- spring.datasource.druid.slave-gamma.username =root
117
- spring.datasource.druid.slave-gamma.password =123456
118
-
119
- # Druid dataSource config
120
- spring.datasource.type =com.alibaba.druid.pool.DruidDataSource
121
- spring.datasource.druid.initial-size =5
122
- spring.datasource.druid.max-active =20
123
- spring.datasource.druid.min-idle =5
124
- spring.datasource.druid.max-wait =60000
125
- spring.datasource.druid.pool-prepared-statements =false
126
- spring.datasource.druid.validation-query =SELECT 1
127
- spring.datasource.druid.validation-query-timeout =30000
128
- spring.datasource.druid.test-on-borrow =false
129
- spring.datasource.druid.test-on-return =false
130
- spring.datasource.druid.test-while-idle =true
131
- # spring.datasource.druid.time-between-eviction-runs-millis=
132
- # spring.datasource.druid.min-evictable-idle-time-millis=
133
- # spring.datasource.druid.max-evictable-idle-time-millis=10000
134
-
135
- # Druid stat filter config
136
- spring.datasource.druid.filters =stat,wall,log4j
137
- spring.datasource.druid.web-stat-filter.enabled =true
138
- spring.datasource.druid.web-stat-filter.url-pattern =/*
139
- spring.datasource.druid.web-stat-filter.exclusions =*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*
140
- spring.datasource.druid.web-stat-filter.session-stat-enable =true
141
- spring.datasource.druid.web-stat-filter.session-stat-max-count =10
142
- spring.datasource.druid.web-stat-filter.principal-session-name =user
143
- # spring.datasource.druid.web-stat-filter.principal-cookie-name=
144
- spring.datasource.druid.web-stat-filter.profile-enable =true
145
- spring.datasource.druid.filter.stat.db-type =mysql
146
- spring.datasource.druid.filter.stat.log-slow-sql =true
147
- spring.datasource.druid.filter.stat.slow-sql-millis =1000
148
- spring.datasource.druid.filter.stat.merge-sql =true
149
- spring.datasource.druid.filter.wall.enabled =true
150
- spring.datasource.druid.filter.wall.config.delete-allow =true
151
- spring.datasource.druid.filter.wall.config.drop-table-allow =false
152
- spring.datasource.druid.filter.slf4j.enabled =true
153
- # Druid manage page config
154
- spring.datasource.druid.stat-view-servlet.enabled =true
155
- spring.datasource.druid.stat-view-servlet.url-pattern =/druid/*
156
- spring.datasource.druid.stat-view-servlet.reset-enable =true
157
- spring.datasource.druid.stat-view-servlet.login-username =admin
158
- spring.datasource.druid.stat-view-servlet.login-password =admin
159
- # spring.datasource.druid.stat-view-servlet.allow=
160
- # spring.datasource.druid.stat-view-servlet.deny=
161
- spring.datasource.druid.use-global-data-source-stat =true
162
- # Druid AOP config
163
- spring.datasource.druid.aop-patterns =cn.com.hellowood.dynamicdatasource.service.*
164
- spring.aop.proxy-target-class =true
114
+ spring.datasource.hikari.slave-gamma.name =SlaveGamma
115
+ spring.datasource.hikari.slave-gamma.driver-class-name =com.mysql.jdbc.Driver
116
+ spring.datasource.hikari.slave-gamma.jdbc-url =jdbc:mysql://localhost/product_slave_gamma?useSSL =false
117
+ spring.datasource.hikari.slave-gamma.port =3306
118
+ spring.datasource.hikari.slave-gamma.username =root
119
+ spring.datasource.hikari.slave-gamma.password =123456
165
120
166
- # MyBatis config
167
- mybatis.type-aliases-package =cn.com.hellowood.dynamicdatasource.mapper
168
- mybatis.mapper-locations =mappers/**Mapper.xml
121
+ spring.aop.proxy-target-class =true
169
122
server.port =9999
170
123
```
171
124
@@ -216,7 +169,7 @@ public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
216
169
package cn.com.hellowood.dynamicdatasource.configuration ;
217
170
218
171
import org.mybatis.spring.SqlSessionFactoryBean ;
219
- import org.springframework.boot.autoconfigure. jdbc.DataSourceBuilder ;
172
+ import org.springframework.boot.jdbc.DataSourceBuilder ;
220
173
import org.springframework.boot.context.properties.ConfigurationProperties ;
221
174
import org.springframework.context.annotation.Bean ;
222
175
import org.springframework.context.annotation.Configuration ;
@@ -239,9 +192,9 @@ public class DataSourceConfigurer {
239
192
*/
240
193
@Bean (" master" )
241
194
@Primary
242
- @ConfigurationProperties (prefix = " spring.datasource.druid .master" )
195
+ @ConfigurationProperties (prefix = " spring.datasource.hikari .master" )
243
196
public DataSource master () {
244
- return DruidDataSourceBuilder . create(). build();
197
+ return DataSourceBuilder . create(). build();
245
198
}
246
199
247
200
/**
@@ -250,9 +203,9 @@ public class DataSourceConfigurer {
250
203
* @return the data source
251
204
*/
252
205
@Bean (" slaveAlpha" )
253
- @ConfigurationProperties (prefix = " spring.datasource.druid .slave-alpha" )
206
+ @ConfigurationProperties (prefix = " spring.datasource.hikari .slave-alpha" )
254
207
public DataSource slaveAlpha () {
255
- return DruidDataSourceBuilder . create(). build();
208
+ return DataSourceBuilder . create(). build();
256
209
}
257
210
258
211
/**
@@ -261,9 +214,9 @@ public class DataSourceConfigurer {
261
214
* @return the data source
262
215
*/
263
216
@Bean (" slaveBeta" )
264
- @ConfigurationProperties (prefix = " spring.datasource.druid .slave-beta" )
217
+ @ConfigurationProperties (prefix = " spring.datasource.hikari .slave-beta" )
265
218
public DataSource slaveBeta () {
266
- return DruidDataSourceBuilder . create(). build();
219
+ return DataSourceBuilder . create(). build();
267
220
}
268
221
269
222
/**
@@ -274,7 +227,7 @@ public class DataSourceConfigurer {
274
227
@Bean (" slaveGamma" )
275
228
@ConfigurationProperties (prefix = " spring.datasource.druid.slave-gamma" )
276
229
public DataSource slaveGamma () {
277
- return DruidDataSourceBuilder . create(). build();
230
+ return DataSourceBuilder . create(). build();
278
231
}
279
232
280
233
/**
@@ -316,6 +269,10 @@ public class DataSourceConfigurer {
316
269
@ConfigurationProperties (prefix = " mybatis" )
317
270
public SqlSessionFactoryBean sqlSessionFactoryBean () {
318
271
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean ();
272
+ // 配置 MyBatis
273
+ sqlSessionFactoryBean. setTypeAliasesPackage(" cn.com.hellowood.dynamicdatasource.mapper" );
274
+ sqlSessionFactoryBean. setMapperLocations(new PathMatchingResourcePatternResolver (). getResources(" mappers/**Mapper.xml" ));
275
+
319
276
// 配置数据源,此处配置为关键配置,如果没有将 dynamicDataSource 作为数据源则不能实现切换
320
277
sqlSessionFactoryBean. setDataSource(dynamicDataSource());
321
278
return sqlSessionFactoryBean;
@@ -347,18 +304,11 @@ import org.slf4j.LoggerFactory;
347
304
348
305
import java.util.ArrayList ;
349
306
import java.util.List ;
350
- import java.util.concurrent.locks.Lock ;
351
- import java.util.concurrent.locks.ReentrantLock ;
352
307
353
308
public class DynamicDataSourceContextHolder {
354
309
355
310
private static final Logger logger = LoggerFactory . getLogger(DynamicDataSourceContextHolder . class);
356
311
357
- /**
358
- * 用于在切换数据源时保证不会被其他线程修改
359
- */
360
- private static Lock lock = new ReentrantLock ();
361
-
362
312
/**
363
313
* 用于轮循的计数器
364
314
*/
@@ -400,7 +350,6 @@ public class DynamicDataSourceContextHolder {
400
350
* 当使用只读数据源时通过轮循方式选择要使用的数据源
401
351
*/
402
352
public static void useSlaveDataSource () {
403
- lock. lock();
404
353
405
354
try {
406
355
int datasourceKeyIndex = counter % slaveDataSourceKeys. size();
@@ -410,9 +359,7 @@ public class DynamicDataSourceContextHolder {
410
359
logger. error(" Switch slave datasource failed, error message is {}" , e. getMessage());
411
360
useMasterDataSource();
412
361
e. printStackTrace();
413
- } finally {
414
- lock. unlock();
415
- }
362
+ }
416
363
}
417
364
418
365
/**
@@ -467,7 +414,7 @@ import org.springframework.stereotype.Component;
467
414
public class DynamicDataSourceAspect {
468
415
private static final Logger logger = LoggerFactory . getLogger(DynamicDataSourceAspect . class);
469
416
470
- private final String [] QUERY_PREFIX = {" select " };
417
+ private final String [] QUERY_PREFIX = {" get " };
471
418
472
419
@Pointcut (" execution( * cn.com.hellowood.dynamicdatasource.mapper.*.*(..))" )
473
420
public void daoAspect () {
@@ -483,7 +430,7 @@ public class DynamicDataSourceAspect {
483
430
}
484
431
}
485
432
486
- @After (" daoAspect()) " )
433
+ @After (" daoAspect()" )
487
434
public void restoreDataSource (JoinPoint point ) {
488
435
DynamicDataSourceContextHolder . clearDataSourceKey();
489
436
logger. info(" Restore DataSource to [{}] in Method [{}]" ,
0 commit comments