之前在根据https://blog.csdn.net/z357904947/article/details/89157281这个博主的博客完成了数据库动态加载数据的实现。
这个博主有发他的代码链接,所以结合博客很快就实现了。
但是后来总觉得自己搞得代码有点low,之后这个博主回复了我的评论说他改成mybatis-plus了,说mybatis-plus实现了动态数据源。咱也不好意思麻烦别人就自己去看文档了。主要是如何从数据库中加载配置信息,这部分官方预留了接口,后面主要写我怎么实现官方接口的。
官方文档基础项目:https://mp.baomidou.com/guide/dynamic-datasource.html
至于动态增删改查有官方文档 https://github.com/baomidou/dynamic-datasource-spring-boot-starter/wiki/Manual-Add-Remove-DataSource
注解的使用 : https://github.com/baomidou/dynamic-datasource-spring-boot-starter/wiki/Dynamic-Analysis-DataSource
版本应该影响不大我这里贴一下我的相关依赖
com.alibaba
druid-spring-boot-starter
1.1.21
com.baomidou
mybatis-plus-boot-starter
3.1.0
com.baomidou
dynamic-datasource-spring-boot-starter
2.5.4
这就是我用的druid和mybatis-plus的相关依赖版本。
第一个类是配置信息类主要配置一下分页插件和对应自己写的数据库加载方式类
package com.bonc.ioc.config;
import com.bonc.ioc.base.page.PagePlugin;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
/**
* Created by wo on 2018-04-03.
*/
@Configuration
public class DataSourceConfig {
@Value("${spring.datasource.dynamic.datasource.mysql.driverClassName}")
private String driverClassName;
@Value("${spring.datasource.dynamic.datasource.mysql.url}")
private String url;
@Value("${spring.datasource.dynamic.datasource.mysql.username}")
private String username;
@Value("${spring.datasource.dynamic.datasource.mysql.password}")
private String password;
@Bean
public MysqlDynamicDataSourceProvider mysqlDynamicDataSourceProvider(){
MysqlDynamicDataSourceProvider mysqlDynamicDataSourceProvider =
new
MysqlDynamicDataSourceProvider(driverClassName,url,username,password);
return mysqlDynamicDataSourceProvider;
}
@Bean(name="pagePlugin")
@Primary
public PagePlugin pagePlugin(){
return new PagePlugin();
}
}
另一个类继承了提供的抽象类,以在启动时能够运行。
package com.bonc.ioc.config;
import com.baomidou.dynamic.datasource.provider.AbstractJdbcDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import org.springframework.beans.factory.annotation.Autowired;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
/**
* 通过Mysql数据库获取数据源信息
*/
public class MysqlDynamicDataSourceProvider extends AbstractJdbcDataSourceProvider{
public static final String mysqlDriver = "net.sf.log4jdbc.sql.jdbcapi.DriverSpy"; // mysql数据库的驱动类
public static final String oracleDriver = "oracle.jdbc.OracleDriver"; // oracles数据库的驱动类
public static final String sql2005Driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; // sqlserver数据库的驱动类
public static final String sql2000driver = "net.sourceforge.jtds.jdbc.Driver"; // sqlserver数据库的驱动类
public MysqlDynamicDataSourceProvider(String driverClassName, String url, String username, String password) {
super(driverClassName, url, username, password);
}
@Override
protected Map executeStmt(Statement statement) throws SQLException {
Map map = new HashMap<>();
ResultSet rs = statement.executeQuery("select * from facts_dbconnection");
/**
* 获取信息
*/
while(rs.next()){
String databaseType = rs.getString("db_type");
String driverClassName = null;
if (databaseType.equals("MYSQL")) {
driverClassName = mysqlDriver;
} else if (databaseType.equals("ORACLE")) {
driverClassName = oracleDriver;
} else if (databaseType.equals("SQLServer2000")) {
driverClassName = sql2005Driver;
} else if(databaseType.equals("SQLServer")) {
driverClassName = sql2000driver;
}
String url = rs.getString("db_url");
String username = rs.getString("db_username");
String password = rs.getString("db_password");
String key = rs.getString("db_name");
DataSourceProperty dataSourceProperty = new DataSourceProperty();
dataSourceProperty.setPollName(key);
dataSourceProperty.setDriverClassName(driverClassName);
dataSourceProperty.setUrl(url);
dataSourceProperty.setUsername(username);
dataSourceProperty.setPassword(password);
map.put(key,dataSourceProperty);
}
return map;
}
}
代码很简单就是加载相关信息往DataSourceProperty类中放置,并起个切换时的名字,就以key-value的方式往map容器里面放了,然后返回容器。
写完实现简单讲一下原理:
我们继承的类中loadDataSources方法会调用我实现的executeStmt方法得到我要返回得数据源信息并加载到spring容器之中。
至于为啥会运行它呢,
我简单理一个路径
首先mybatis-plus时要实现spring提供得接口,重写相关方法,这个重要得spring类就是org.springframework.jdbc.datasource.AbstractDataSource
之后 mybatis-plus 有一个抽象类(com.baomidou.dynamic.datasource.AbstractRoutingDataSource)继承了它
然后类com.baomidou.dynamic.datasource.DynamicRoutingDataSource继承了该抽象类并实现了InitializingBean, DisposableBean两个接口,在重写afterPropertiesSet接口时调用了loadDataSources()方法,以配置dataSourceMap容器内容。
而dataSourceMap容器其实就是mybatis-plus实现得数据源容器。简单的说你往dataSourceMap里放完在spring容器中你就可以找到你放入的数据源了(略过n多原理,我大致能理解但是实在不会说,还有懒得打字...)。
网上好多都是将的多数据源的,配置在配置文件里的,翻来覆去的,感觉都是拷贝粘贴的,这里要感谢mybatis-plus,还有我文章开头的博主,不然我自己肯定搞不定的,毕竟菜~~~~