【Mybatis】MyBatis之配置⾃定义数据源(⼗⼀)
本例是在的基础上进⾏拓展,查看本例请先学习第⼗章
实现原理
1、扩展Spring的AbstractRoutingDataSource抽象类(该类充当了DataSource的路由中介, 能有在运⾏时, 根据某种key值来动态切换到真正的DataSource上。)
从AbstractRoutingDataSource的源码中,有⼀个数据源查属性(dataSourceLookup),和⼀个查询数据源⽅法(resolveSpecifiedDataSource):
1private DataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
2
3
4protected DataSource resolveSpecifiedDataSource(Object dataSource) throws IllegalArgumentException {
5if (dataSource instanceof DataSource) {
6return (DataSource) dataSource;
7 }
8else if (dataSource instanceof String) {
9return DataSource((String) dataSource);
10 }
11else {
12throw new IllegalArgumentException(
13 "Illegal data source value - only [javax.sql.DataSource] and String supported: " + dataSource);
14 }
15 }
2、类中数据源查类使⽤的是JndiDataSourceLookup,此类查的是JNDI数据源,参考:
3、我们可以⾃定义动态数据源查类来,来控制⾃定义数据源
实现案例
1、搭建项⽬,参考:
2、⾃定义数据源查类
st.datasource;
2
3import java.beans.PropertyVetoException;
4import java.sql.SQLException;
5import java.util.Map;
6import urrent.ConcurrentHashMap;
7
8import javax.sql.DataSource;
9
10import org.springframework.jdbc.datasource.lookup.DataSourceLookup;
11import org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException;
12import org.springframework.util.Assert;
13
hange.v2.c3p0.ComboPooledDataSource;
15
16public class DynamicDataSourceLookup implements DataSourceLookup {
17
18/**
19 * 数据源集合
20*/
21private final Map<String, DataSource> dataSources = new ConcurrentHashMap<>();
22
23/**
24 * 根据数据源名称,获取数据源
25*/
26 @Override
27public DataSource getDataSource(String dataSourceName) throws DataSourceLookupFailureException {
28
29 Null(dataSourceName, "DataSourceName must not be null");
30 DataSource dataSource = (dataSourceName);
31if (dataSource == null) {
32// datasource not in map.. create one and add to map
33 dataSource = createDataSource(dataSourceName);
34if(dataSource != null) {
35 addDataSource(dataSourceName, dataSource);
36 }
37 }
38// 记录数据源状态
39if(dataSource instanceof ComboPooledDataSource) {
40 ComboPooledDataSource ds = (ComboPooledDataSource) dataSource;
41try {
42 System.out.println("ds.getMaxPoolSize():" + ds.getMaxPoolSize());// 最⼤连接数
43 System.out.println("ds.getMaxPoolSize():" + ds.getMaxPoolSize());// 最⼤连接数
44 System.out.println("ds.getMinPoolSize():" + ds.getMinPoolSize());// 最⼩连接数
45 System.out.println("ds.getNumBusyConnections():" + ds.getNumBusyConnections());// 正在使⽤连接数
46 System.out.println("ds.getNumIdleConnections():" + ds.getNumIdleConnections());// 空闲连接数
47 System.out.println("ds.getNumConnections():" + ds.getNumConnections());
48 } catch (SQLException e) {
49// TODO Auto-generated catch block
50 e.printStackTrace();
51 }// 总连接数
52 }
53return dataSource;
54 }
55
56/**
57 * 创建数据源
58 * @param dataSourceName
59 * @return
60*/
61private DataSource createDataSource(String dataSourceName) {
62
63 ComboPooledDataSource dataSource = null;
64
65// 可根据其他业务数据,创建数据源
66try {
67 dataSource = new ComboPooledDataSource();
68 dataSource.setUser("admin");
69 dataSource.setPassword("123456");
70 dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/test_mybatis?allowPublicKeyRetrieval=true");
71 dataSource.setDriverClass("sql.jdbc.Driver");
72 dataSource.setDataSourceName(dataSourceName);
73
74
75 } catch (PropertyVetoException e) {
76throw new RuntimeException("Error creating data source");
77 }
78return dataSource;
79 }
80
81/**
82 * 添加数据源到数据源集合中
83 * @param dataSourceName
84 * @param dataSource
85*/
86public void addDataSource(String dataSourceName, DataSource dataSource) {
87 Null(dataSourceName, "DataSourceName must not be null");
88 Null(dataSource, "DataSource must not be null");
89this.dataSources.put(dataSourceName, dataSource);
90 }
91
92/**
93 * 从数据源集合移除数据源
94 * @param dataSourceName
95*/
96public void removeDataSource(String dataSourceName) {
97 Null(dataSourceName, "DataSourceName must not be null");
ve(dataSourceName);
99 }
100
101 }
3、编辑动态数据源类,从写determineTargetDataSource⽅法,查询数据源时,先从⾃定义数据源中查,然后从内部数据源中查 st.datasource;
2
3import javax.sql.DataSource;
4
5import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
6
7/**
8 * 动态数据源(依赖于spring)
9 * @author chenheng
10 * @date 2019-08-03 17:27:35
11 *
12*/
13public class DynamicDataSource extends AbstractRoutingDataSource {
14
15 @Override
16protected Object determineCurrentLookupKey() {
DataSourceKey();
18 }
19
20 @Override
21protected DataSource determineTargetDataSource() {
22
23 Object lookupKey = determineCurrentLookupKey();
24 DataSource dataSource = null;
25// ⾃定义外部数据源类中,查询数据源
26if(lookupKey != null) {
27 dataSource = resolveSpecifiedDataSource(key);
28 }
29// 在内部数据源中,查询数据源
30if(dataSource == null){
31 dataSource= super.determineTargetDataSource();
32 }
33return dataSource;
34 }
35 }
4、注⼊dynamicDataSourceLookup,并且在dataSource注⼊属性dataSourceLookup
1<bean id="dynamicDataSourceLookup" class="st.datasource.DynamicDataSourceLookup">
2</bean>
3
4
5<!-- 数据源:Spring⽤来控制业务逻辑。数据源、事务控制、aop -->
6<bean id="dataSource" class="st.datasource.DynamicDataSource">
7<property name="targetDataSources">
8<map key-type="java.lang.String">
9<entry key="dataSource1" value-ref="dataSource1"></entry>
10<entry key="dataSource2" value-ref="dataSource2"></entry>
11</map>
12</property>
13<!-- 默认⽬标数据源为你主库数据源 -->
14<property name="defaultTargetDataSource" ref="dataSource1"/>
15<property name="dataSourceLookup" ref="dynamicDataSourceLookup"/>
16</bean>
5、编辑是⼀个动态数据源DAO,来使⽤⾃定动态数据源
st.dao;
2
3
4import javax.sql.DataSource;
5
6import org.springframework.beans.factory.annotation.Autowired;
7import org.support.JdbcDaoSupport;
8import org.springframework.stereotype.Repository;
9
10
11 @Repository
12public class DynamicDao extends JdbcDaoSupport {
13
14 @Autowired
15public DynamicDao(DataSource dataSource) {
16this.setDataSource(dataSource);
17 }
18
19 }
6、在Service中使⽤
st.service;
2
3import java.util.List;
4
5import org.springframework.beans.factory.annotation.Autowired;
6import org.BeanPropertyRowMapper;
7import org.springframework.stereotype.Service;
8
st.dao.DynamicDao;
st.datasource.DataSourceHolder;
st.pojo.Employee;
12
13 @Service
14public class DynamicService {
15
16 @Autowired
17 DynamicDao dynamicDao;
18jdbctemplate查询一条数据
19public List<Employee> getEmployee() {
20 DataSourceHolder.setDataSourceKey("⾃定义");
JdbcTemplate().query("select id, last_name lastName, gender, email from employee", 22new BeanPropertyRowMapper<>(Employee.class));
23 }
24
25 }
数据流转顺序:
1.在 DataSourceHolder中,设置数据源名称
2.Spring 调⽤determineCurrentLookupKey()⽅法<DynamicDataSource中重写AbstractRoutingDataSource类中的⽅法> ,从DataSourceHolder取出当前的数据库名称,并返回
3.AbstractRoutingDataSource类中determineTargetDataSource()⽅法调⽤determineCurrentLookupKe
y(),先匹配外部数据库,然后匹配内部数据库;
4.匹配到指定的数据库,并建⽴链接,即为切换到相应的数据库;
5.在指定的数据库中执⾏相应的sql
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论