最近遇到一个问题,项目中用的是mybatis-plus,配置了多个数据库,不打印sql日志;
网上一大堆说yml中配置的,但是配置后执行sql会报错:table不存在,不能用。
java.sql.SQLSyntaxErrorException: Table 'main_db.user_msg' doesn't exist
user_msg表确实不在main_db库中,在另一个库user_db中。
本人分析,yml中配置后,mybatis-plus就会用另一个SqlSessionFactory了,而不会使用java中配置的多个SqlSessionFactory(配多个是多数据库用的,各用各的),导致选择了默认库,找不到表;
如果不在yml中配置,就没有问题,但不配又不打日志。
所以解决方法为,在配置SQLSessionFactory的java类中增加以下代码:
MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setLogImpl(StdOutImpl.class);
//factory是自己创建的,类型是SqlSessionFactory
factory.setConfiguration(configuration);
然后就能打印sql日志了。
-----------------------------------------------------------------------------
备注1:以下是较完整的多个数据库用的配置类的代码:
(1)yml中增加参数,方便控制:
mybatis-plus-print-log: true
(2)java代码,是主库的factory:
@Configuration
public class MainDBConfig{
//从yml中获得值,如果没有得到,则使用:后的,为false
@Value("${mybatis-plus-print-log:false}")
private String isLog;
@Autowired
private ApplicationContext applicationContext;
//这里是主库的url,main_db
@Value("${spring.datasource.url}")
private String url;
//bean放入spring容器后的名称
@Bean(name="dataSource")
//从properties中读取的参数是前缀为spring.datasource的参数
@ConfigurationProperties(prefix="spring.datasource")
public DataSource dataSource(){
return DataSourceBuilder.create().url(url).build();
}
@Bean
public PlatformTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name="sqlSessionFactory")
//必须有一个主factory
@Primary
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource")DataSource dataSource, MybatisPlusProperties properties, ResourceLoader resourceLoader, ObjectProvider<Interceptor[]> interceptorsProvider, ObjectProvider<DatabaseIdProvider> datebaseIdProvider, ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) throws Exception {
Interceptor[] interceptors = interceptorsProvider.getIfAvailable();
DatabaseIdProvider databaseIdProvider1 = databaseIdProvider.getIfAvailable();
List<ConfigurationCustomizer> configurationCustomizers = configurationCustomizersProvider.getIfAvailable();
//factory的bean
MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setVfs(SpringBootVFS.class);
if(StringUtils.hasText(properties.getConfigLocation())){
factory.setConfigLocation(resourceLoader.getResource(properties.getConfigLocation()));
}
applyConfiguration(factory,properties,configurationCustomizers);
if(properties.getConfigurationProperties()!=null){
factory.setConfigurationProperties(properties.getConfigurationProperties());
}
if(!ObjectUtils.isEmpty(interceptors)){
factory.setPlugins(interceptors);
}
if(databaseIdProvider1 != null ){
factory.setDatabaseIdProvider(databaseIdProvider1);
}
if(StringUtils.hasLength(properties.getTypeAliasesPackage())){
factory.setTypeAliasesPackage(properties.getTypeAliasesPackage());
}
if(properties.getTypeAliasesSupterType() !=null){
factory.setTypeAliasesSupterType(properties.getTypeAliasesSupterType());
}
if(StringUtils.hasLength(properties.getTypeHandlerPackage())){
factory.setTypeHandlerPackage(properties.getTypeHandlerPackage());
}
if(!ObjectUtils.isEmpty(properties.resolveMapperLocations())){
factory.setMapperLocations(properties.resolveMapperLocations());
}
if(StringUtils.hasLength(properties.getTypeEnumsPackage())){
factory.setTypeEnumsPackage(properties.getTypeEnumsPackage());
}
GlobalConfig globalConfig = properties.getGlobalConfig();
if(applicationContext.getBeanNamesForType(MetaObjectHandler.class,false,false).length>0){
MetaObjectHandler metaObjectHandler = applicationContext.getBean(MetaObjectHandler.class);
globalConfig.setMetaObjectHandler(metaObjectHandler);
}
if(applicationContext.getBeanNamesForType(IKeyGenerator.class,false,false).length>0){
IKeyGenerator iKeyGenerator = applicationContext.getBean(IKeyGenerator.class);
globalConfig.getDbConfig().setKeyGenerator(iKeyGenerator);
}
if(applicationContext.getBeanNamesForType(ISqlInjector.class,false,false).length>0){
ISqlInjector iSqlInjector = applicationContext.getBean(ISqlInjector.class);
globalConfig.setSqlInjector(iSqlInjector);
}
factory.setGlobalConfig(globalConfig);
return factory.getObject();
}
private void applyConfiguration(MybatisSqlSessionFactoryBean factory, MybatisPlusProperties properties, List<ConfigurationCustomizer> configurationCustomizers){
MybatisConfiguration conf = properties.getConfiguration();
if(conf == null && !StringUtils.hasText(properties.getConfigLocation()){
conf = new MybatisConfiguration();
}
if(conf != null && !CollectionUtils.isEmpty(configurationCustomizers)){
for(ConfigurationCustomizer customizer : configurationCustomizers){
customizer.customize(configuration);
}
}
//这里根据yml的参数判断是否打日志
if("true".equals(isLog)){
if(conf == null){
conf = new MybatisConfiguration();
}
conf.setLogImpl(StdOutImpl.class);
}
factory.setConfiguration(conf);
}
}
(3)其余数据库的factory与上方类似,简要记录下不同之处:
@Configuration
//这里不一样
@ConditionalOnProperty("user_db.id")
//这里不一样,指定某个包下的dao层用这个factory(进而用另一个库)
@MapperScan(basePackages={"com.xxx.user.repo"}), sqlSessionFactoryRef="userSqlSessionFactory")
public class UserDBConfig{
@Value("${mybatis-plus-print-log:false}")
private String isLog;
@Autowired
private AplicationContext applicationContext;
//这里不一样,bean名称
@Bean(name="userDBDataSource")
//这里不一样,指定不同前缀,用另一个库的url
@ConfigurationProperties(prefix="spring.datasource.user")
public DataSource dataDbDataSource(){
//这里不一样,不用传入url
return DataSourceBuilder.create().build();
}
//没有PlatformTransactionManager
//这里不一样,bean名
@Bean(name="userSqlSessionFactory")
//这里不一样,没有Primary
//这里不一样,qualifier用另一个
public SqlSessionFactory sqlSessionFactory(@Qualifier("userDBDataSource")DataSource dataSource, MybatisPlusProperties properties, ResourceLoader resourceLoader, ObjectProvider<Interceptor[]> interceptorsProvider, ObjectProvider<DatabaseIdProvider> datebaseIdProvider, ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) throws Exception {
//这里面都一样
......
}
private void applyConfiguration(MybatisSqlSessionFactoryBean factory, MybatisPlusProperties properties, List<ConfigurationCustomizer> configurationCustomizers){
//这里面都一样
......
}
}
备注2:
yml打印日志的配置,当项目没有使用java自定义SQLSessionFactory时可用:
mybatis-plus:
#如果是mybatis,就把-plus删掉
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl