一、多數據源的應用場景
目前,業界流行的數據操作框架是 Mybatis,那 Druid 是什么呢?
Druid 是 Java 的數據庫連接池組件。Druid 能夠提供強大的監控和擴展功能。比如可以監控 SQL ,在監控業務可以查詢慢查詢 SQL 列表等。Druid 核心主要包括三部分:
1. DruidDriver 代理 Driver,能夠提供基于 Filter-Chain 模式的插件體系。
2. DruidDataSource 高效可管理的數據庫連接池
3. SQLParser
當業務數據量達到了一定程度,DBA 需要合理配置數據庫資源。即配置主庫的機器高配置,把核心高頻的數據放在主庫上;把次要的數據放在從庫,低配置。開源節流嘛,就這個意思。把數據放在不同的數據庫里,就需要通過不同的數據源進行操作數據。這里我們舉個 springboot-mybatis-mutil-datasource 工程案例:
user 用戶表在主庫 master 上,地址表 city 在從庫 cluster 上。下面實現獲取 根據用戶名獲取用戶信息,包括從庫的地址信息 REST API,那么需要從主庫和從庫中分別獲取數據,并在業務邏輯層組裝返回。邏輯如圖:
下面就運行這個案例。
二、運行 springboot-mybatis-mutil-datasource 工程案例
工程項目地址: springboot-learning.rar。下面開始運行工程步驟:
1.數據庫準備
a.創建 cluster 數據庫 springbootdb:
1
|
CREATE DATABASE springbootdb; |
b.創建表 city :(因為我喜歡徒步)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
DROP TABLE IF EXISTS `city`; CREATE TABLE `city` ( `id` int (10) unsigned NOT NULL AUTO_INCREMENT COMMENT '城市編號' , `province_id` int (10) unsigned NOT NULL COMMENT '省份編號' , `city_name` varchar (25) DEFAULT NULL COMMENT '城市名稱' , `description` varchar (25) DEFAULT NULL COMMENT '描述' , PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; |
c.插入數據
1
|
INSERT city VALUES (1 ,1, '溫嶺市' , 'BYSocket 的家在溫嶺。' ); |
然后,再創建一個 master 數據庫
a.創建數據庫 springbootdb_cluster:
1
|
CREATE DATABASE springbootdb_cluster; |
b.創建表 user :
1
2
3
4
5
6
7
8
9
10
11
12
13
|
DROP TABLE IF EXISTS `city`; CREATE TABLE user ( id INT (10) unsigned PRIMARY KEY NOT NULL COMMENT '用戶編號' AUTO_INCREMENT, user_name VARCHAR (25) COMMENT '用戶名稱' , description VARCHAR (25) COMMENT '描述' )ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; |
c.插入數據
1
|
INSERT user VALUES (1 , '泥瓦匠' , '他有一個小網站 bysocket.com' ); |
(以上數據庫創建無先后順序)
2. 項目結構介紹
項目結構如下圖所示:
- org.spring.springboot.config.ds – 配置層,這里是數據源的配置,包括 master 和 cluster 的數據源配置
- org.spring.springboot.controller – Controller 層
- org.spring.springboot.dao – 數據操作層 DAO,細分了 master 和 cluster 包下的 DAO 操作類
- org.spring.springboot.domain – 實體類
- org.spring.springboot.service – 業務邏輯層
- Application – 應用啟動類
- application.properties – 應用配置文件,應用啟動會自動讀取配置
3.改數據庫配置
打開 application.properties 文件, 修改相應的主從數據源配置,比如數據源地址、賬號、密碼等。(如果不是用 MySQL,自行添加連接驅動 pom,然后修改驅動名配置。)
4.編譯工程
在項目根目錄 springboot-learning-example,運行 maven 指令:
1
|
mvn clean install |
5.運行工程
右鍵運行 Application 應用啟動類(位置:/springboot-learning-example/springboot-mybatis-mutil-datasource/src/main/java/org/spring/springboot/Application.java)的 main 函數,這樣就成功啟動了 springboot-mybatis-mutil-datasource 案例。
在瀏覽器打開:http://localhost:8080/api/user?userName=泥瓦匠
瀏覽器返回 JSON 結果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
{ "id" : 1, "userName" : "泥瓦匠" , "description" : "他有一個小網站 bysocket.com" , "city" : { "id" : 1, "provinceId" : 1, "cityName" : "溫嶺市" , "description" : "BYSocket 的家在溫嶺。" } } |
這里 city 結果體來自 cluster 庫,user 結果體來自 master 庫。
三、springboot-mybatis-mutil-datasource 工程代碼配置詳解
首先代碼工程結構如下:
org.spring.springboot.config.ds 包包含了多數據源的配置,同樣有第三個數據源,按照前幾個復制即可
resources/mapper 下面有兩個模塊,分別是 Mybatis 不同數據源需要掃描的 mapper 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
|
├── pom.xml └── src └── main ├── java │ └── org │ └── spring │ └── springboot │ ├── Application.java │ ├── config │ │ └── ds │ │ ├── ClusterDataSourceConfig.java │ │ └── MasterDataSourceConfig.java │ ├── controller │ │ └── UserRestController.java │ ├── dao │ │ ├── cluster │ │ │ └── CityDao.java │ │ └── master │ │ └── UserDao.java │ ├── domain │ │ ├── City.java │ │ └── User.java │ └── service │ ├── UserService.java │ └── impl │ └── UserServiceImpl.java └── resources ├── application.properties └── mapper ├── cluster │ └── CityMapper.xml └── master └── UserMapper.xml |
1. 依賴 pom.xml
Mybatis 通過 Spring Boot Mybatis Starter 依賴
Druid 是數據庫連接池依賴
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
<? xml version = "1.0" encoding = "UTF-8" ?> < project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < modelVersion >4.0.0</ modelVersion > < groupId >springboot</ groupId > < artifactId >springboot-mybatis-mutil-datasource</ artifactId > < version >0.0.1-SNAPSHOT</ version > < name >springboot-mybatis-mutil-datasource :: Spring Boot 實現 Mybatis 多數據源配置</ name > <!-- Spring Boot 啟動父依賴 --> < parent > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-parent</ artifactId > < version >1.5.1.RELEASE</ version > </ parent > < properties > < mybatis-spring-boot >1.2.0</ mybatis-spring-boot > < mysql-connector >5.1.39</ mysql-connector > < druid >1.0.18</ druid > </ properties > < dependencies > <!-- Spring Boot Web 依賴 --> < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-web</ artifactId > </ dependency > <!-- Spring Boot Test 依賴 --> < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-test</ artifactId > < scope >test</ scope > </ dependency > <!-- Spring Boot Mybatis 依賴 --> < dependency > < groupId >org.mybatis.spring.boot</ groupId > < artifactId >mybatis-spring-boot-starter</ artifactId > < version >${mybatis-spring-boot}</ version > </ dependency > <!-- MySQL 連接驅動依賴 --> < dependency > < groupId >mysql</ groupId > < artifactId >mysql-connector-java</ artifactId > < version >${mysql-connector}</ version > </ dependency > <!-- Druid 數據連接池依賴 --> < dependency > < groupId >com.alibaba</ groupId > < artifactId >druid</ artifactId > < version >${druid}</ version > </ dependency > <!-- Junit --> < dependency > < groupId >junit</ groupId > < artifactId >junit</ artifactId > < version >4.12</ version > </ dependency > </ dependencies > </ project > |
2. application.properties 配置兩個數據源配置
數據源配置會被數據源數據源配置如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
## master 數據源配置 master.datasource.url=jdbc:mysql: //localhost:3306/springbootdb?useUnicode=true&characterEncoding=utf8 master.datasource.username=root master.datasource.password= 123456 master.datasource.driverClassName=com.mysql.jdbc.Driver ## cluster 數據源配置 cluster.datasource.url=jdbc:mysql: //localhost:3306/springbootdb_cluster?useUnicode=true&characterEncoding=utf8 cluster.datasource.username=root cluster.datasource.password= 123456 cluster.datasource.driverClassName=com.mysql.jdbc.Driver |
3. 數據源配置
多數據源配置的時候注意,必須要有一個主數據源,即 MasterDataSourceConfig 配置:
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
|
@Configuration // 掃描 Mapper 接口并容器管理 @MapperScan (basePackages = MasterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "masterSqlSessionFactory" ) public class MasterDataSourceConfig { // 精確到 master 目錄,以便跟其他數據源隔離 static final String PACKAGE = "org.spring.springboot.dao.master" ; static final String MAPPER_LOCATION = "classpath:mapper/master/*.xml" ; @Value ( "${master.datasource.url}" ) private String url; @Value ( "${master.datasource.username}" ) private String user; @Value ( "${master.datasource.password}" ) private String password; @Value ( "${master.datasource.driverClassName}" ) private String driverClass; @Bean (name = "masterDataSource" ) @Primary public DataSource masterDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driverClass); dataSource.setUrl(url); dataSource.setUsername(user); dataSource.setPassword(password); return dataSource; } @Bean (name = "masterTransactionManager" ) @Primary public DataSourceTransactionManager masterTransactionManager() { return new DataSourceTransactionManager(masterDataSource()); } @Bean (name = "masterSqlSessionFactory" ) @Primary public SqlSessionFactory masterSqlSessionFactory( @Qualifier ( "masterDataSource" ) DataSource masterDataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(masterDataSource); sessionFactory.setMapperLocations( new PathMatchingResourcePatternResolver() .getResources(MasterDataSourceConfig.MAPPER_LOCATION)); return sessionFactory.getObject(); } } |
@Primary 標志這個 Bean 如果在多個同類 Bean 候選時,該 Bean 優先被考慮。「多數據源配置的時候注意,必須要有一個主數據源,用 @Primary 標志該 Bean」
@MapperScan 掃描 Mapper 接口并容器管理,包路徑精確到 master,為了和下面 cluster 數據源做到精確區分
@Value 獲取全局配置文件 application.properties 的 kv 配置,并自動裝配
sqlSessionFactoryRef 表示定義了 key ,表示一個唯一 SqlSessionFactory 實例
同理可得,從數據源 ClusterDataSourceConfig 配置如下:
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
|
@Configuration // 掃描 Mapper 接口并容器管理 @MapperScan (basePackages = ClusterDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "clusterSqlSessionFactory" ) public class ClusterDataSourceConfig { // 精確到 cluster 目錄,以便跟其他數據源隔離 static final String PACKAGE = "org.spring.springboot.dao.cluster" ; static final String MAPPER_LOCATION = "classpath:mapper/cluster/*.xml" ; @Value ( "${cluster.datasource.url}" ) private String url; @Value ( "${cluster.datasource.username}" ) private String user; @Value ( "${cluster.datasource.password}" ) private String password; @Value ( "${cluster.datasource.driverClassName}" ) private String driverClass; @Bean (name = "clusterDataSource" ) public DataSource clusterDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(driverClass); dataSource.setUrl(url); dataSource.setUsername(user); dataSource.setPassword(password); return dataSource; } @Bean (name = "clusterTransactionManager" ) public DataSourceTransactionManager clusterTransactionManager() { return new DataSourceTransactionManager(clusterDataSource()); } @Bean (name = "clusterSqlSessionFactory" ) public SqlSessionFactory clusterSqlSessionFactory( @Qualifier ( "clusterDataSource" ) DataSource clusterDataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(clusterDataSource); sessionFactory.setMapperLocations( new PathMatchingResourcePatternResolver() .getResources(ClusterDataSourceConfig.MAPPER_LOCATION)); return sessionFactory.getObject(); } } |
上面數據配置分別掃描 Mapper 接口,org.spring.springboot.dao.master(對應 xml classpath:mapper/master ) 和 org.spring.springboot.dao.cluster(對應 xml classpath:mapper/cluster ) 包中對應的 UserDAO 和 CityDAO 。
都有 @Mapper 標志為 Mybatis 的并通過容器管理的 Bean。Mybatis 內部會使用反射機制運行去解析相應 SQL。
3.業務層 biz
biz 照常注入了兩個 DAO,如同以前一樣正常工作。不用關心和指定到具體說明數據源。
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
|
/** * 用戶業務實現層 * * Created by bysocket on 07/02/2017. */ @Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; // 主數據源 @Autowired private CityDao cityDao; // 從數據源 @Override public User findByName(String userName) { User user = userDao.findByName(userName); City city = cityDao.findByName( "溫嶺市" ); user.setCity(city); return user; } } |
四、小結
多數據源適合的場景很多。不同的 DataSource ,不同的 SqlSessionFactory 和 不同的 DAO 層,在業務邏輯層做 整合。總結的架構圖如下:
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.cnblogs.com/Alandre/p/6611813.html