java_Springboot_Mybatis-Plus_自定义多数据源MybatisSqlSessionFactoryBean配置方法
目录
- java_Springboot_Mybatis-Plus_自定义多数据源MybatisSqlSessionFactoryBean配置方法
- 引言
- 环境
- 集成过程中遇到的问题
- Invalid bound statement (not found) 错误
- 默认数据源问题
- 测试数据源是否正确
- 总结
引言
需要在服务中集成表结构维护的功能,维护表结构就需要使用具有执行DDL脚本权限的账号。
为了保证系统的安全性,考虑在工程中配置多个数据源引入不同权限账号,高权限账号只在特定逻辑中使用,其它默认业务使用低权限账号。
加入新的数据源不能影响已有的功能,保证已有功能继续使用只具有CRUD权限的账号。
看了几个多数据源接入方案,都不太满足需求。
- Springboot默认支持的多数据源
- Mybatis-Plus的多数据源既动态数据源dynamic-datasource插件
- Alibaba Druid动态数据源
环境
- JDK 1.0
- SpringBoot 1.5.6
- Mybaits 3.5.3
- Mybatis-plus 3.3.1
集成过程中遇到的问题
Invalid bound statement (not found) 错误
由于系统中调用了Mybatis-plus的BaseMapper中的扩展方法selectBatchIds(),
调用selectBatchIds()方法的位置都报:Invalid bound statement (not found) 错误。
一般遇到这种问题基本都是接口中定义的方法名在对应的XML文件中没有定义。
但是现在使用的是com.baomidou.mybatisplus.core.mapper.BaseMapper中的扩展方法,不需要在XML中定义的!
问题产生原因是没有使用Mybatis-Plust自定义的MybatisSqlSessionFactoryBean构建 SqlSessionFactory实例导致,
改用后解决了Invalid bound statement (not found)的问题。
@Bean(name = "defSqlSessionFactory")@Primarypublic SqlSessionFactory defSqlSessionFactory(@Qualifier("defDataSource") DataSource dataSource) throws Exception {MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();//SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dataSource);//设置mybatis的xml所在位置Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath:com/.../mapper/**/*Mapper.xml");bean.setMapperLocations(resources);SqlSessionFactory factory = bean.getObject();return factory;}
默认数据源问题
配置多个数据源时,必须明确声明DataSource、SqlSessionFactory、PlatformTransactionManager、SqlSessionTemplate关键对象!
在默认的Bean上加@Primary注解,标记为默认配置。以下为同一数据源的Bean配置,多个数据源需要加入多套配置。
@Configuration
public class DbDefaultConfig {@Bean(name = "defDataSource")@Primary@ConfigurationProperties(prefix = "spring.datasource")public DataSource defDataSource() {DataSource datasource = DataSourceBuilder.create().build();return datasource;}@Bean(name = "defSqlSessionFactory")@Primarypublic SqlSessionFactory defSqlSessionFactory(@Qualifier("defDataSource") DataSource dataSource) throws Exception {MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();//SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setDataSource(dataSource);//设置mybatis的xml所在位置Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath:com/.../mapper/**/*Mapper.xml");bean.setMapperLocations(resources);SqlSessionFactory factory = bean.getObject();return factory;}/*** JDBC事务管理器* @param dataSource* @return*/@Bean("defTransactionManager")@Primarypublic PlatformTransactionManager txManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Bean(name = "defSqlSessionTemplate")@Primarypublic SqlSessionTemplate defSqlSessionTemplate(@Qualifier("defSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);return sqlSessionTemplate;}
}
测试数据源是否正确
@RunWith(SpringRunner.class)
//@Transactional
@SpringBootTest(classes = StartApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@ActiveProfiles("")
public class MultiDatasourceTest {@Autowiredprivate List<SqlSessionFactory> sqlSessionFactoryList;@Beforepublic void before(){}@Testpublic void datasourceTest(){System.out.println("sqlSessionFactoryList Size = " + sqlSessionFactoryList.size());boolean success = true;for(SqlSessionFactory f:sqlSessionFactoryList ){System.out.println("【工厂】:"+f.toString());try {datasourceTest(f);System.out.println("成功!!!");}catch (Exception ex){System.out.println("异常:"+ex.toString());if(success)success = false;}}Assert.assertTrue("存在不支持的查询!",success);}private boolean datasourceTest(SqlSessionFactory factory){MyTestMapper mapper = factory.openSession(true).getMapper(MyTestMapper.class);//xml中的方法Object objPk = mapper.selectByPrimaryKey("111");//mybatis-plus BaseMapper 中的扩展方法(使用前必须在对象上加 @TableName,pk字段上加@TableId注解)Object objIds = mapper.selectBatchIds(Arrays.asList("1","2"));return true;}
}
总结
构建SqlSessionFactory必须使用MybatisPlust实现的MybatisSqlSessionFactoryBean对象,原理没有深入的去看。
梳理了一下Mapper实例的构建过程,发现调用的扩展方法必须继承BaseMapper类,Mapper实例又是通过SqlSessionFactory实例创建的,
大概率Mapper扩展方法绑定在MybatisSqlSessionFactoryBean的实例方法bean.getObject()中实现的。