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> 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 extends LanguageDriver> 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