前言:
我不太喜欢AOP读自定义注解来切换数据源.因为如果我一个业务里需要同时查2个数据源的数据而又不想把这个业务拆成2个方法的时候,就比较麻烦了.
所以我打算根据package来扫描注入不同的DataSource.可能是我搜索的姿势不太对 , 资料比较少.也会碰到不少坑.所以记录一下.
正文:
mybatis 和 mybatisplus的区别不大 ,一起记了.
springboot 和 mybatis jar就不说了.
druid的jar⬇️
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
- 配置数据库连接信息
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
# psi 库
psi:
url: jdbc:postgresql://127.0.0.1:5432/psidb
driver-class-name: org.postgresql.Driver
username: username
password: password
# b2b 库
b2badapter:
url: jdbc:mysql://127.0.0.1:13306/b2b?useSSL=false&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=UTF-8&characterSetResults=UTF-8&allowMultiQueries=true
driver-class-name: com.mysql.jdbc.Driver
username: username
password: username
其实就是在spring.datasource.druid下再指定2个连接.
2.有了连接信息, 就去代码配置DataSource的Bean了.
@Configuration
public class DataSourceConfig {
/**
* PSI 库连接配置前缀 (与 yml 中的连接信息前缀一致 , 下同)
*/
private static final String PSI_DATASOURCE_PREFIX = "spring.datasource.druid.psi";
/**
* PSI 库连接Bean名字
*/
public static final String PSI_DATASOURCE_BEAN_NAME = "psiDataSource";
/**
* B2B 库中间库连接配置前缀
*/
private static final String B2B_DATASOURCE_PREFIX = "spring.datasource.druid.b2badapter";
/**
* B2B 库中间库连接Bean名字
*/
public static final String B2B_DATASOURCE_BEAN_NAME = "b2bDataSource";
@Primary
@Bean(name = PSI_DATASOURCE_BEAN_NAME)
@ConfigurationProperties(prefix = PSI_DATASOURCE_PREFIX)
public DruidDataSource psi() {
return new DruidDataSource();
}
@Bean(name = B2B_DATASOURCE_BEAN_NAME)
@ConfigurationProperties(prefix = B2B_DATASOURCE_PREFIX)
public DruidDataSource b2b() {
return new DruidDataSource();
}
}
这个@Primary还是有点用, 等下说.
3.配置每个库对应的SqlSessionFactory
以第一个库(psi)举例
@Configuration
@MapperScan(basePackages = "com.a.b.c.d.e.psi.dao", sqlSessionTemplateRef = "psiSqlSessionTemplate")
public class PsiDataSourceConfig {
@Autowired
@Qualifier(DataSourceConfig.PSI_DATASOURCE_BEAN_NAME)
private DataSource psi;
@Primary
@Bean("psiSqlSessionFactory")
public SqlSessionFactory psiSqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
factoryBean.setDataSource(psi);
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
configuration.setJdbcTypeForNull(JdbcType.NULL);
factoryBean.setConfiguration(configuration);
//指定xml路径.
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/a/b/c/d/e/psi/mapper/*Dao.xml"));
return factoryBean.getObject();
}
@Primary
@Bean("psiSqlSessionTemplate")
public SqlSessionTemplate psiSqlSessionTemplate() throws Exception {
SqlSessionTemplate template = new SqlSessionTemplate(psiSqlSessionFactory()); // 使用上面配置的Factory
return template;
}
}
算了, 第二个也放上来吧
@Configuration
@MapperScan(basePackages = "com.a.b.c.d.e.b2b.dao", sqlSessionTemplateRef = "b2bSqlSessionTemplate")
public class B2BDataSourceConfig {
@Autowired
@Qualifier(DataSourceConfig.B2B_DATASOURCE_BEAN_NAME)
private DataSource b2b;
@Bean("b2bSqlSessionFactory")
public SqlSessionFactory b2bSqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
factoryBean.setDataSource(b2b);
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
configuration.setJdbcTypeForNull(JdbcType.NULL);
factoryBean.setConfiguration(configuration);
//指定xml路径.
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/a/b/c/d/e/b2b/mapper/*Dao.xml"));
factoryBean.setPlugins(new Interceptor[]{
new PaginationInterceptor(),
new PerformanceInterceptor(),
new OptimisticLockerInterceptor()
});
return factoryBean.getObject();
}
@Bean("b2bSqlSessionTemplate")
public SqlSessionTemplate b2bSqlSessionTemplate() throws Exception {
SqlSessionTemplate template = new SqlSessionTemplate(b2bSqlSessionFactory()); // 使用上面配置的Factory
return template;
}
}
这个配置是MybatisPlus的MybatisSqlSessionFactoryBean,通过这个类才能使用MybatisPlus的BaseMapper
如果只是Mybatis的话...
@Bean
public SqlSessionFactory mysqlSqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(b2b);
//指定xml路径.
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/a/b/c/d/e/b2b/mapper/*Dao.xml"));
return factoryBean.getObject();
}
普通的SqlSessionFactoryBean就行了..
这2个数据源就是通过类上的
@MapperScan(basePackages = "com.a.b.c.d.e.b2b.dao")
来扫描项目不同包下的Mapper文件来注入不同的数据源.
如果,万一,在某些情况下. 2个MapperScan扫描到重复的包怎么办.....谁有@Primary就谁上..
4.最后的最后.去掉springboot/jpa,druid等的自动配置
在启动类上(当然你也可以在yml里去配)加上
@SpringBootApplication(exclude = {
DruidDataSourceAutoConfigure.class,
DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
JpaRepositoriesAutoConfiguration.class
})
如果是Mybatis的话,.. 只用去掉DataSourceAutoConfiguration.class应该就行了
/..
然后, 没了吧. 就可以用了.