package cn.stylefeng.guns.base.db.collector; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.stylefeng.roses.kernel.model.exception.ServiceException; import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer; import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties; import com.baomidou.mybatisplus.autoconfigure.MybatisPlusPropertiesCustomizer; import com.baomidou.mybatisplus.autoconfigure.SpringBootVFS; import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.core.config.GlobalConfig; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator; import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; import com.baomidou.mybatisplus.core.injector.ISqlInjector; import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils; import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.mapping.DatabaseIdProvider; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.scripting.LanguageDriver; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.type.TypeHandler; import org.springframework.beans.factory.ObjectProvider; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ResourceLoader; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import javax.sql.DataSource; import java.util.List; import java.util.Optional; import java.util.concurrent.ConcurrentSkipListSet; import java.util.function.Consumer; /** * mybatis的一些配置收集 *

* 本类copy自com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration,改了sqlSessionFactory() * 主要是为了让多个SqlSessionFactory初始化的过程中使用各自的配置类,因为mapper在加载的时候有缓存 * * @author fengshuonan * @date 2019-06-15-18:30 */ @Data @Slf4j @Configuration public class SqlSessionFactoryCreator { private final MybatisPlusProperties properties; private final Interceptor[] interceptors; private final TypeHandler[] typeHandlers; private final LanguageDriver[] languageDrivers; private final ResourceLoader resourceLoader; private final DatabaseIdProvider databaseIdProvider; private final List configurationCustomizers; private final List mybatisPlusPropertiesCustomizers; private final ApplicationContext applicationContext; public SqlSessionFactoryCreator(MybatisPlusProperties properties, ObjectProvider interceptorsProvider, ObjectProvider typeHandlersProvider, ObjectProvider languageDriversProvider, ResourceLoader resourceLoader, ObjectProvider databaseIdProvider, ObjectProvider> configurationCustomizersProvider, ObjectProvider> mybatisPlusPropertiesCustomizerProvider, ApplicationContext applicationContext) { this.properties = properties; this.interceptors = interceptorsProvider.getIfAvailable(); this.typeHandlers = typeHandlersProvider.getIfAvailable(); this.languageDrivers = languageDriversProvider.getIfAvailable(); this.resourceLoader = resourceLoader; this.databaseIdProvider = databaseIdProvider.getIfAvailable(); this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable(); this.mybatisPlusPropertiesCustomizers = mybatisPlusPropertiesCustomizerProvider.getIfAvailable(); this.applicationContext = applicationContext; } /** * 创建SqlSessionFactory */ public synchronized SqlSessionFactory createSqlSessionFactory(DataSource dataSource) { //初始化本MybatisSqlSessionFactoryBean需要的配置,如果不初始化,则所有MybatisSqlSessionFactoryBean都用一套配置,会出现mapper语句差不不进去(因为mp的缓存) MybatisConfiguration originConfiguration = properties.getConfiguration(); GlobalConfig originGlobalConfig = properties.getGlobalConfig(); //清空mapper的缓存 originGlobalConfig.setMapperRegistryCache(new ConcurrentSkipListSet<>()); //创建新的配置 MybatisConfiguration mybatisConfiguration = new MybatisConfiguration(); GlobalConfig globalConfig = GlobalConfigUtils.defaults(); //执行拷贝操作 BeanUtil.copyProperties(originConfiguration, mybatisConfiguration, CopyOptions.create().ignoreError()); BeanUtil.copyProperties(originGlobalConfig, globalConfig, CopyOptions.create().ignoreError()); mybatisConfiguration.setGlobalConfig(globalConfig); // TODO 使用 MybatisSqlSessionFactoryBean 而不是 SqlSessionFactoryBean MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setVfs(SpringBootVFS.class); if (StringUtils.hasText(this.properties.getConfigLocation())) { factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation())); } if (this.properties.getConfigurationProperties() != null) { factory.setConfigurationProperties(this.properties.getConfigurationProperties()); } if (!ObjectUtils.isEmpty(this.interceptors)) { factory.setPlugins(this.interceptors); } if (this.databaseIdProvider != null) { factory.setDatabaseIdProvider(this.databaseIdProvider); } if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) { factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage()); } if (this.properties.getTypeAliasesSuperType() != null) { factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType()); } if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) { factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage()); } if (!ObjectUtils.isEmpty(this.typeHandlers)) { factory.setTypeHandlers(this.typeHandlers); } if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) { factory.setMapperLocations(this.properties.resolveMapperLocations()); } // TODO 对源码做了一定的修改(因为源码适配了老旧的mybatis版本,但我们不需要适配) Class defaultLanguageDriver = this.properties.getDefaultScriptingLanguageDriver(); if (!ObjectUtils.isEmpty(this.languageDrivers)) { factory.setScriptingLanguageDrivers(this.languageDrivers); } Optional.ofNullable(defaultLanguageDriver).ifPresent(factory::setDefaultScriptingLanguageDriver); // TODO 自定义枚举包 if (StringUtils.hasLength(this.properties.getTypeEnumsPackage())) { factory.setTypeEnumsPackage(this.properties.getTypeEnumsPackage()); } // TODO 注入填充器 this.getBeanThen(MetaObjectHandler.class, globalConfig::setMetaObjectHandler); // TODO 注入主键生成器 this.getBeanThen(IKeyGenerator.class, i -> globalConfig.getDbConfig().setKeyGenerator(i)); // TODO 注入sql注入器 this.getBeanThen(ISqlInjector.class, globalConfig::setSqlInjector); // TODO 注入ID生成器 this.getBeanThen(IdentifierGenerator.class, globalConfig::setIdentifierGenerator); // TODO 设置 GlobalConfig 到 MybatisSqlSessionFactoryBean factory.setGlobalConfig(globalConfig); try { return factory.getObject(); } catch (Exception e) { log.error("初始化SqlSessionFactory错误!", e); throw new ServiceException(500, "初始化SqlSessionFactory错误!"); } } /** * 检查spring容器里是否有对应的bean,有则进行消费 * * @param clazz class * @param consumer 消费 * @param 泛型 */ private void getBeanThen(Class clazz, Consumer consumer) { if (this.applicationContext.getBeanNamesForType(clazz, false, false).length > 0) { consumer.accept(this.applicationContext.getBean(clazz)); } } }