项目背景:项目开发中数据库使用了读写分离,所有查询语句走从库,除此之外走主库。
最简单的办法其实就是建两个包,把之前数据源那一套配置copy一份,指向另外的包,但是这样扩展很有限,所有采用下面的办法。
参考了两篇文章如下:
https://www.zzvips.com/article/104411.html
https://www.zzvips.com/article/104412.html
这两篇文章都对原理进行了分析,下面只写自己的实现过程其他不再叙述。
实现思路是:
第一步,实现动态切换数据源:配置两个DataSource,配置两个SqlSessionFactory指向两个不同的DataSource,两个SqlSessionFactory都用一个SqlSessionTemplate,同时重写Mybatis提供的SqlSessionTemplate类,最后配置Mybatis自动扫描。
第二步,利用aop切面,拦截dao层所有方法,因为dao层方法命名的特点,比如所有查询sql都是select开头,或者get开头等等,拦截这些方法,并把当前数据源切换至从库。
spring中配置如下:
主库数据源配置:
?
1
2
3
4
5
|
<bean id= "masterDataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method= "close" > 2 <property name= "driverClass" value= "${master_mysql_jdbc_driver}" />
<property name= "jdbcUrl" value= "${master_mysql_jdbc_url}" />
<property name= "user" value= "${master_mysql_jdbc_user}" />
<property name= "password" value= "${master_mysql_jdbc_password}" />
</bean>
|
从库数据源配置:
?
1
2
3
4
5
6
|
<bean id= "masterDataSource" class = "com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method= "close" >
<property name= "driverClass" value= "${slave_mysql_jdbc_driver}" />
<property name= "jdbcUrl" value= "${slave_mysql_jdbc_url}" />
<property name= "user" value= "${slave_mysql_jdbc_user}" />
<property name= "password" value= "${slave_mysql_jdbc_password}" />
</bean>
|
主库SqlSessionFactory配置:
?
1
2
3
4
|
<bean id= "masterSqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean" >
<property name= "dataSource" ref= "masterDataSource" />
<property name= "mapperLocations" value= "classpath:com/sincetimes/slg/dao/*.xml" />
</bean>
|
从库SqlSessionFactory配置:
?
1
2
3
4
|
<bean id= "slaveSqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean" >
<property name= "dataSource" ref= "slaveDataSource" />
<property name= "mapperLocations" value= "classpath:com/sincetimes/slg/dao/*.xml" />
</bean>
|
两个SqlSessionFactory使用同一个SqlSessionTemplate配置:
?
1
2
3
4
5
6
7
8
9
|
<bean id= "MasterAndSlaveSqlSessionTemplate" class = "com.sincetimes.slg.framework.core.DynamicSqlSessionTemplate" >
<constructor-arg index= "0" ref= "masterSqlSessionFactory" />
<property name= "targetSqlSessionFactorys" >
<map>
<entry value-ref= "masterSqlSessionFactory" key= "master" />
<entry value-ref= "slaveSqlSessionFactory" key= "slave" />
</map>
</property>
</bean>
|
配置Mybatis自动扫描dao
?
1
2
3
4
|
<bean class = "org.mybatis.spring.mapper.MapperScannerConfigurer" >
<property name= "basePackage" value= "com.sincetimes.slg.dao" />
<property name= "sqlSessionTemplateBeanName" value= "MasterAndSlaveSqlSessionTemplate" />
</bean>
|
自己重写了SqlSessionTemplate代码如下:
?
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|