Directorio de artículos
Prefacio
Durante el desarrollo de un proyecto, a menudo nos encontramos con situaciones en las que necesitamos conectarnos a varias bases de datos. O el caso de múltiples bases de datos diferentes. Este artículo trata sobre la implementación de múltiples conexiones de fuentes de datos usando el marco SpringBoot + Mybatis. La base de datos usa SQL Server. ¡Ojalá te haya ayudado!
1. Importe el paquete Jar requerido (pom.xml)
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- Druid 数据连接池依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.11</version>
</dependency>
<!--SQL Server-->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<scope>runtime</scope>
</dependency>
<!--SpringBoot 添加jdbc支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
2. Definir constantes de dos bases de datos.
El código es el siguiente (ejemplo):
/**
* @author 孤巷.
* @description
* @date 2022/8/9 15:58
*/
public class DataBaseNameConstant {
/**
* HIS数据库
*/
public static final String HIS = "his";
/**
* 预约挂号数据库
*/
public static final String APPOINTMENT = "appointment";
}
3. Cree carpetas dao y mapper
(1) Distinga dos fuentes de datos en el directorio de la carpeta dao
(2) Distinga dos fuentes de datos en la carpeta del asignador
4. Crear una clase de configuración de fuente de datos
Cree una fuente de datos de carpeta y cree cinco nuevas clases de configuración en ella.
El código específico es el siguiente:
(1) Fuente de datos
import java.lang.annotation.*;
/**
* mybatis自定义注解,用来声明数据源
*
* @author wcs
*/
@Target({
ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String value();
}
(2)Aspecto de fuente de datos
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* mybatis切面,用来切换数据源
*
* @author wcs
*/
@Aspect
@Component
@Slf4j
public class DataSourceAspect {
@Pointcut("execution(* com.example.web.dao.*.*.*(..))")
public void dataSourcePointCut() {
}
@Before("dataSourcePointCut()")
public void before(JoinPoint point) {
Object target = point.getTarget();
DataSource dataSource = target.getClass().getInterfaces()[0].getAnnotation(DataSource.class);
if (dataSource != null) {
String key = dataSource.value();
log.info("当前运行的数据源为 == {}",key);
DynamicDataSourceHolder.setDataSource(key);
}
}
}
(3)Configuración de fuente de datos
import com.alibaba.druid.pool.DruidDataSource;
import com.example.web.constant.DataBaseNameConstant;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* @author wcs
* @description 多数据源配置
* @date 2021/3/13 11:44
*/
@Configuration
public class DatasourceConfig {
@Bean(name = DataBaseNameConstant.HIS)
@ConfigurationProperties(prefix = "spring.datasource.druid.his")
public DataSource hisDruid() {
return new DruidDataSource();
}
@Bean(name = DataBaseNameConstant.APPOINTMENT)
@ConfigurationProperties(prefix = "spring.datasource.druid.appointemnt")
public DataSource appointemntDruid() {
return new DruidDataSource();
}
@Bean
@Primary
public DynamicDataSource dataSource() {
Map<String, DataSource> targetDataSources = new HashMap<>(4);
targetDataSources.put(DataBaseNameConstant.HIS, hisDruid());
targetDataSources.put(DataBaseNameConstant.APPOINTMENT, appointemntDruid());
return new DynamicDataSource(targetDataSources.get(DataBaseNameConstant.HIS), targetDataSources);
}
}
(4)Fuente de datos dinámica
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* mybatis自定义数据源
*
* @author wcs
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
public DynamicDataSource(DataSource defaultTargetDataSource, Map<String, DataSource> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(new HashMap<>(targetDataSources));
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder.getDataSouce();
}
}
(5)Soporte de fuente de datos dinámicos
/**
* mybatis自定义数据源管理器
*
* @author wcs
*/
public class DynamicDataSourceHolder {
public static final ThreadLocal<String> holder = new ThreadLocal<String>();
public static void setDataSource(String name) {
holder.set(name);
}
public static String getDataSouce() {
return holder.get();
}
}
5. Defina el archivo de la aplicación.
提示:本文中还会用到lombok以及Druid,这两个jar包在网上都能找到
(1)
El código del contenido del archivo Application.yml es el siguiente:
#开发环境配置
server:
port: 9803
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
datasource:
druid:
his:
url: jdbc:sqlserver://127.0.0.1:1433;databaseName=test;
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
username: test
password: test
initial-size: 5 #初始化时建立物理连接的个数。
max-active: 20 #最大连接池数量
min-idle: 5 #最小连接池数量
max-wait: 3000 #获取连接时最大等待时间,单位毫秒
pool-prepared-statements: false #是否缓存preparedStatement,也就是PSCache,PSCache对支持游标的数据库性能提升巨大,比如说oracle,在mysql下建议关闭。
#要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
max-open-prepared-statements: 100
time-between-eviction-runs-millis: 60000 #配置检测可以关闭的空闲连接间隔时间
min-evictable-idle-time-millis: 300000 # 配置连接在池中的最小生存时间
max-evictable-idle-time-millis: 400000
filters: stat,slf4j #监控统计的stat,以及防sql注入的wall
web-stat-filter:
enabled: true
validation-query: SELECT 1
# StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
#是否启用StatViewServlet(监控页面)默认值为false(考虑到安全问题默认并未启动,如需启用建议设置密码或白名单以保障安全)
stat-view-servlet:
enabled: true #是否启用StatViewServlet默认值true
url-pattern: /druid/* #访问路径为/druid时,跳转到StatViewServlet
reset-enable: true #是否能够重置数据
login-username: whxx
login-password: whxx666.
allow: localhost
test-on-borrow: false
test-on-return: false
test-while-idle: true
max-pool-prepared-statement-per-connection-size: 20
filter:
stat:
log-slow-sql: true
slow-sql-millis: 2000
slf4j:
enabled: true
result-set-log-enabled: false
statement-create-after-log-enabled: false
statement-close-after-log-enabled: false
result-set-open-after-log-enabled: false
result-set-close-after-log-enabled: false
appointemnt:
url: jdbc:sqlserver://127.0.0.1:1433;databaseName=test1;
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
username: test1
password: test1
initial-size: 5 #初始化时建立物理连接的个数。
max-active: 20 #最大连接池数量
min-idle: 5 #最小连接池数量
max-wait: 3000 #获取连接时最大等待时间,单位毫秒
pool-prepared-statements: false #是否缓存preparedStatement,也就是PSCache,PSCache对支持游标的数据库性能提升巨大,比如说oracle,在mysql下建议关闭。
#要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
max-open-prepared-statements: 100
time-between-eviction-runs-millis: 60000 #配置检测可以关闭的空闲连接间隔时间
min-evictable-idle-time-millis: 300000 # 配置连接在池中的最小生存时间
max-evictable-idle-time-millis: 400000
filters: stat,slf4j #监控统计的stat,以及防sql注入的wall
web-stat-filter:
enabled: true
validation-query: SELECT 1
# StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
#是否启用StatViewServlet(监控页面)默认值为false(考虑到安全问题默认并未启动,如需启用建议设置密码或白名单以保障安全)
stat-view-servlet:
enabled: true #是否启用StatViewServlet默认值true
url-pattern: /druid/* #访问路径为/druid时,跳转到StatViewServlet
reset-enable: true #是否能够重置数据
login-username: whxx
login-password: whxx666.
allow: localhost
test-on-borrow: false
test-on-return: false
test-while-idle: true
max-pool-prepared-statement-per-connection-size: 20
filter:
stat:
log-slow-sql: true
slow-sql-millis: 2000
slf4j:
enabled: true
result-set-log-enabled: false
statement-create-after-log-enabled: false
statement-close-after-log-enabled: false
result-set-open-after-log-enabled: false
result-set-close-after-log-enabled: false
mybatis:
mapper-locations: classpath:mapper/*/*.xml #xml文件位置
type-aliases-package: com.example.web.bean
configuration:
map-underscore-to-camel-case: true
call-setters-on-nulls: true #处理数据为null时键值对不存在
Resumir
El código de esta publicación se ha publicado y puede hacer otras preguntas en el área de comentarios a continuación, ¡y el blogger le dará una respuesta a tiempo! ¡Gracias por su atención!