当前环境
IntelliJ IDEA 2023.1
springboot3.2.0
jdk17.0.9
数据源为不同数据库
application.yml配置
mybatis:
type-aliases-package: com.oa.**.po
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true
spring:
datasource:
qs:
jdbc-url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=Hongkong&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: 123
driver-class-name: com.mysql.cj.jdbc.Driver
hjldb:
jdbc-url: jdbc:sqlserver://127.0.0.1:3433;Database=test
username: root
password: 123
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
分别为两个数据库创建两个configuration
@Configuration
@MapperScan(
basePackages = {"com.oa.sys.mapper", "com.oa.quartz.mapper", "com.oa.persistence.mapper"},
sqlSessionFactoryRef = "qsSqlSessionFactory",
sqlSessionTemplateRef = "qsSqlSessionTemplate"
)
public class DataSourceConfig_qs {
@Bean
@ConfigurationProperties(prefix = "mybatis.configuration")
public org.apache.ibatis.session.Configuration qsConfiguration() {
return new org.apache.ibatis.session.Configuration();
}
/**
* 加载数据源
*
* @return
*/
@Bean(name = "qs")
@ConfigurationProperties(prefix = "spring.datasource.qs")
@Primary
public DataSource qsDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "qsSqlSessionFactory")
@Primary
public SqlSessionFactory qsSqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource, org.apache.ibatis.session.Configuration qsConfiguration) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
//驼峰映射注册到SqlSessionFactory中
bean.setConfiguration(qsConfiguration);
// 分页插件
Interceptor interceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect", "mysql");
properties.setProperty("reasonable", "true");
interceptor.setProperties(properties);
bean.setPlugins(new Interceptor[] {interceptor});
return bean.getObject();
}
/**
* 添加事务
*
* @param dataSource
* @return
*/
@Bean(name = "qsTransactionManager")
@Primary
public DataSourceTransactionManager qsTransactionManager(@Qualifier("qs") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "qsSqlSessionTemplate")
@Primary
public SqlSessionTemplate qsSqlSessionTemplate(@Qualifier("qsSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
@Configuration
@MapperScan(
basePackages = {"com.oa.persistence.hjldbMapper"},
sqlSessionFactoryRef = "hjldbSqlSessionFactory",
sqlSessionTemplateRef = "hjldbSqlSessionTemplate"
)
public class DataSourceConfig_hjldb {
/**
* 加载数据源
*
* @return
*/
@Bean(name = "hjldb")
@ConfigurationProperties(prefix = "spring.datasource.hjldb")
public DataSource hjldbDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "hjldbSqlSessionFactory")
public SqlSessionFactory hjldbSqlSessionFactory(@Qualifier("hjldb") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
// 分页插件
Interceptor interceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect", "sqlserver");
properties.setProperty("reasonable", "true");
interceptor.setProperties(properties);
bean.setPlugins(new Interceptor[] {interceptor});
return bean.getObject();
}
/**
* 添加事务
*
* @param dataSource
* @return
*/
@Bean(name = "hjldbTransactionManager")
public DataSourceTransactionManager hjldbTransactionManager(@Qualifier("hjldb") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "hjldbSqlSessionTemplate")
public SqlSessionTemplate hjldbSqlSessionTemplate(@Qualifier("hjldbSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
数据源为主从库
application.yml配置
mybatis:
type-aliases-package: com.oa.**.po
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true
spring:
datasource:
qs:
jdbc-url: jdbc:mysql://127.0.0.1:3306/qs?serverTimezone=Hongkong&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: 123
driver-class-name: com.mysql.cj.jdbc.Driver
slave:
jdbc-url: jdbc:mysql://192.168.16.12:3306/qs?serverTimezone=Hongkong&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: 123
driver-class-name: com.mysql.cj.jdbc.Driver
创建configuration
@Configuration
@MapperScan(
basePackages = {"com.oa.sys.mapper", "com.oa.quartz.mapper", "com.oa.persistence.mapper"},
sqlSessionFactoryRef = "qsSqlSessionFactory",
sqlSessionTemplateRef = "qsSqlSessionTemplate"
)
public class DataSourceConfig_qs {
@Bean
@ConfigurationProperties(prefix = "mybatis.configuration")
public org.apache.ibatis.session.Configuration qsConfiguration() {
return new org.apache.ibatis.session.Configuration();
}
/**
* 加载数据源
*
* @return
*/
@Bean(name = "qs")
@ConfigurationProperties(prefix = "spring.datasource.qs")
public DataSource qsDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "slave")
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "dynamicDataSource")
public DynamicDataSource dynamicDataSource(@Qualifier("qs")DataSource qsDataSource,@Qualifier("slave")DataSource slaveDataSource){
Map<Object, Object> targetDataSources = new HashMap<>(2);
targetDataSources.put("qs", qsDataSource);
targetDataSources.put("slave", slaveDataSource);
//DynamicDataSource(默认数据源,所有数据源) 第一个指定默认数据库
return new DynamicDataSource(qsDataSource, targetDataSources);
}
@Bean(name = "qsSqlSessionFactory")
public SqlSessionFactory qsSqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource, org.apache.ibatis.session.Configuration qsConfiguration) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
//驼峰映射注册到SqlSessionFactory中
bean.setConfiguration(qsConfiguration);
// 分页插件
Interceptor interceptor = new PageInterceptor();
Properties properties = new Properties();
properties.setProperty("helperDialect", "mysql");
properties.setProperty("reasonable", "true");
interceptor.setProperties(properties);
bean.setPlugins(new Interceptor[] {interceptor});
return bean.getObject();
}
/**
* 添加事务
*
* @param dataSource
* @return
*/
@Bean(name = "qsTransactionManager")
@Primary
public DataSourceTransactionManager qsTransactionManager(@Qualifier("dynamicDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "qsSqlSessionTemplate")
public SqlSessionTemplate qsSqlSessionTemplate(@Qualifier("qsSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
动态数据源DynamicDataSource.java
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
/**
* 配置DataSource, defaultTargetDataSource为主数据库
*/
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}
aop切入动态切换数据库
@Aspect
@Component
@Slf4j
public class DynamicDataSourceAspect{
@Around("@annotation(targetDataSource)")
public Object around(ProceedingJoinPoint point, TargetDataSource targetDataSource) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
TargetDataSource ds = method.getAnnotation(TargetDataSource.class);
// 通过判断 DataSource 中的值来判断当前方法应用哪个数据源
DynamicDataSource.setDataSource(ds.value());
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
}
}
}
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TargetDataSource {
String value() default DataSourceNames.qs; //默认数据库
}
在impl上添加注解即可
@Override
@TargetDataSource(DataSourceNames.slave)
public List<Customer> getAll() {
return customerMapper.selectAll();
}