新的项目需求,需要将子需求A锁定到A库,将子需求B锁定到B库;
就是俗称的“分库”;但这是业务性分库,也就是说,A库和B库并没有任何逻辑上的,主从或水平或垂直分库关系;就是,完全没有关系
。
SpringBoot
可配置多数据源,但项目中使用Druid
进行数据源管理;DataSource
后,需要将DataSource
交给Mybatis的SqlSessionFactory
建立相关连接;SpringBoot的@Configuration注解
使用,方便简洁;spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
master:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://aaa
username: xxxaaa
password: xxxaaa
report:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://bbb
username: xxxbbb
password: xxxbbb
initialSize: 1
minIdle: 3
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 30000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 打开PSCache,并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,slf4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多个DruidDataSource的监控数据
#useGlobalDataSourceStat: true
package com.project.common.config.datasource;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.sql.SQLException;
@SuppressWarnings("AlibabaRemoveCommentedCode")
@MapperScan(basePackages = DruidDBConfig.daoPackages, sqlSessionTemplateRef = "aaaSqlSessionTemplate")
@Configuration
public class DruidDBConfig {
public static final String domainPackages = "com.project.**.domain";
public static final String daoPackages = "com.project.*.dao";
public static final String mapperLocations = "classpath:mybatis/aaa/**/*Mapper.xml";
private Logger logger = LoggerFactory.getLogger(DruidDBConfig.class);
@Value("${spring.datasource.aaa.url}")
private String dbUrl;
@Value("${spring.datasource.aaa.username}")
private String username;
@Value("${spring.datasource.aaa.password}")
private String password;
@Value("${spring.datasource.aaa.driverClassName}")
private String driverClassName;
@Value("${spring.datasource.initialSize}")
private int initialSize;
@Value("${spring.datasource.minIdle}")
private int minIdle;
@Value("${spring.datasource.maxActive}")
private int maxActive;
@Value("${spring.datasource.maxWait}")
private int maxWait;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.testOnReturn}")
private boolean testOnReturn;
@Value("${spring.datasource.poolPreparedStatements}")
private boolean poolPreparedStatements;
@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
private int maxPoolPreparedStatementPerConnectionSize;
@Value("${spring.datasource.filters}")
private String filters;
@Value("{spring.datasource.connectionProperties}")
private String connectionProperties;
@Bean(name = "aaaDataSource", initMethod = "init", destroyMethod = "close") //声明其为Bean实例
@Primary //在同样的DataSource中,首先使用被标注的DataSource
public DataSource aaaDataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(this.dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
//configuration
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setValidationQuery(validationQuery);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
try {
datasource.setFilters(filters);
} catch (SQLException e) {
logger.error("druid configuration initialization filter", e);
}
datasource.setConnectionProperties(connectionProperties);
return datasource;
}
@Bean(name = "aaaSqlSessionFactory")
@Primary
public SqlSessionFactory aaaSqlSessionFactory(@Qualifier("aaaDataSource") DataSource aaaDataSource) throws Exception {
/*
**!: SqlSessionFactory的配置是重点,详细定制Mybatis针对不同数据源的
配置信息,下面几行代码分别配置:
1. Entity包名
2. DB字段名下划线, 映射成, 驼峰命名法
3. Mybatis, Mapper的包所在位置
*/
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(aaaDataSource);
// 扫描Entity
bean.setTypeAliasesPackage(domainPackages);
org.apache.ibatis.session.Configuration conf = new org.apache.ibatis.session.Configuration();
conf.setMapUnderscoreToCamelCase(true);
bean.setConfiguration(conf);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
return bean.getObject();
}
@Bean(name = "aaaTransactionManager")
@Primary
public DataSourceTransactionManager aaaTransactionManager(@Qualifier("aaaDataSource") DataSource aaaDataSource) {
return new DataSourceTransactionManager(aaaDataSource);
}
@Bean(name = "aaaSqlSessionTemplate")
@Primary
public SqlSessionTemplate aaaSqlSessionTemplate(@Qualifier("aaaSqlSessionFactory") SqlSessionFactory aaaSqlSessionFactory) throws Exception {
return new SqlSessionTemplate(aaaSqlSessionFactory);
}
}
bbb
与aaa
配置完全雷同, 可以在上述重点
处调整针对不同数据源的SqlSessionFactory细节
;
public static final String domainPackages = "com.project.**.domain";
public static final String daoPackages = "com.project.*.dao";
public static final String mapperLocations = "classpath:mybatis/aaa/**/*Mapper.xml";
mybatis相关的, Entity
, Dao
, Xml
三层, 不同数据源的文件最好放到不同的包里, 做好资源隔离
, 相信在调试过程中你会遇到很多资源冲突的bug, 祝好运~