基本架构
SpringBoot+MybatisPlus实现多数据源,借助Spring-AOP实现数据源的动态切换.
整体流程
-
定义注解,使用该注解配置具体方法使用的数据源,用于指明方法使用的数据源github
-
定义通知advice:实现接口MethodBeforeAdvice, AfterReturningAdvice,用于在方法的执行前后切换数据源
-
定义切面:这里通过实现接口PointcutAdvisor定义切面,其中定义切点覆盖所有需要拦截的方法(需要操作数据库的方法),引入具体的通知,即上一步定义的advice,并通过注解@Component将其注入到spring容器中
-
定义封装数据源的工具类,使用ThreadLocal存储,通过字符串区分所使用的数据源
public class DataSourceHolder { private static final ThreadLocal<String> DATA_SOURCES = new ThreadLocal<>(); public static void setDataSources(String customerType) { DATA_SOURCES.set(customerType); } public static String getDataSource() { return DATA_SOURCES.get(); } public static void clearDataSource() { DATA_SOURCES.remove(); } }
-
配置数据源的bean,并自定义动态数据源类实现接口AbstractRoutingDataSource,重写determineCurrentLookupKey方法返回多数据源具体的key
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceHolder.getDataSource(); } }
-
配置SqlSessionFactory的bean,设置其数据源为自定义的动态数据源(设置默认数据源以及多数据源Map)
@Bean public SqlSessionFactory sqlSessionFactoryBean() throws Exception { MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean(); // 配置数据源,此处配置为关键配置,如果没有将 dynamicDataSource作为数据源则不能实现切换 sqlSessionFactory.setDataSource(dynamicDataSource()); // 扫描Model sqlSessionFactory.setTypeAliasesPackage("com.zdk.**.entity"); return sqlSessionFactory.getObject(); } @Bean public DynamicDataSource dynamicDataSource() { DynamicDataSource dataSource = new DynamicDataSource(); Map<Object, Object> targetDataSource = new HashMap<>(16); targetDataSource.put("hello-world", helloWorldDataSource()); targetDataSource.put("zdk-data", zdkDataDataSource()); dataSource.setTargetDataSources(targetDataSource); dataSource.setDefaultTargetDataSource(helloWorldDataSource()); return dataSource; }
注意
- 切点的定义问题,注意切点的正则表达式能否覆盖到所有涉及到数据库操作的方法
- 在MybatisPlus中使用MybatisSqlSessionFactoryBean作为SqlSessionFactory而非SqlSessionFactoryBean