由于在主库发现的我的一条SQL的慢查询、之前都是直接连一个数据库、后面让他改成查询的SQL连另一台从库。
于是我第一时间打开了大家的百度、后续总结复制粘贴了一个完整的案例并线上使用了、环境版本不一样可能使用的配置不一样、所以仅供参考。
Spring Boot、Druid、Mybatis、MySQL
org.springframework.boot
spring-boot-starter-parent
2.3.3.RELEASE
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.2
mysql
mysql-connector-java
5.1.25
com.alibaba
druid-spring-boot-starter
1.1.17
spring:
datasource:
master:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
slave:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 123456
# druid 连接池配置接着往下配置就OK
max-active: 12
@Slf4j
public class DynamicDataSource extends AbstractRoutingDataSource {
public static final String MASTER = "MASTER"; // 写
public static final String SLAVE = "SLAVE"; // 读
private static final ThreadLocal DYNAMIC_DATASOURCE_KEY = new ThreadLocal();
public static String getDynamicDataSourceKey() {
String val = DYNAMIC_DATASOURCE_KEY.get();
return val == null ? DynamicDataSource.MASTER : val;
}
public static void setDynamicDataSourceKey(String key) {
DYNAMIC_DATASOURCE_KEY.set(key);
}
public static void removeDynamicDataSourceKey() {
DYNAMIC_DATASOURCE_KEY.remove();
}
@Override
protected Object determineCurrentLookupKey() {
String dynamicDataSourceKey = getDynamicDataSourceKey();
log.info("当前数据源:[{}]", dynamicDataSourceKey);
return dynamicDataSourceKey;
}
}
@Configuration
public class DataSourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource masterDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean("dynamicDataSource")
public DynamicDataSource dynamicDataSource() {
DynamicDataSource dynamicRoutingDataSource = new DynamicDataSource();
Map targetDataSources = new HashMap(2);
targetDataSources.put(DynamicDataSource.MASTER, masterDataSource());
targetDataSources.put(DynamicDataSource.SLAVE, slaveDataSource());
dynamicRoutingDataSource.setDefaultTargetDataSource(slaveDataSource());
dynamicRoutingDataSource.setTargetDataSources(targetDataSources);
dynamicRoutingDataSource.afterPropertiesSet();
return dynamicRoutingDataSource;
}
@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource datasource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(datasource);
// 映射文件地址
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
// 所有Entity别名类所在包
bean.setTypeAliasesPackage("com.suka.entity");
return bean.getObject();
}
}
@Slf4j
@Aspect
@Order(1)
@Component
public class DataSourceAspect {
@Pointcut("execution(* com.suka.mapper.*.*(..))")
public void dsPointCut() {
}
@Around("dsPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
String methodName = signature.getMethod().getName();
// get/sel/select/find 开的头的Mapper类中的方法就切换。
if (methodName.startsWith("get") || methodName.startsWith("sel")
|| methodName.startsWith("select") || methodName.startsWith("find")) {
DynamicDataSource.setDynamicDataSourceKey(DynamicDataSource.SLAVE);
}
try {
return point.proceed();
} finally {
DynamicDataSource.removeDynamicDataSourceKey();
}
}
}
两个注意点:DataSourceAspect类是需要引入AOP依赖、sqlSessionFactory是Mybatis需要的、里面可以配置一些扫描包的配置以及类别名之类相关Mybatis的配置信息。
问题来了、如何校验我这个查询方法或者插入方法是走的那个配置的数据源呢、你去把配置文件中的数据库写一个错的不就可以校验了、如果报错了就证明是用的这个配置的数据源!!!