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的一些配置收集
|
* <p>
|
* 本类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<ConfigurationCustomizer> configurationCustomizers;
|
|
private final List<MybatisPlusPropertiesCustomizer> mybatisPlusPropertiesCustomizers;
|
|
private final ApplicationContext applicationContext;
|
|
public SqlSessionFactoryCreator(MybatisPlusProperties properties,
|
ObjectProvider<Interceptor[]> interceptorsProvider,
|
ObjectProvider<TypeHandler[]> typeHandlersProvider,
|
ObjectProvider<LanguageDriver[]> languageDriversProvider,
|
ResourceLoader resourceLoader,
|
ObjectProvider<DatabaseIdProvider> databaseIdProvider,
|
ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider,
|
ObjectProvider<List<MybatisPlusPropertiesCustomizer>> 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 <T> 泛型
|
*/
|
private <T> void getBeanThen(Class<T> clazz, Consumer<T> consumer) {
|
if (this.applicationContext.getBeanNamesForType(clazz, false, false).length > 0) {
|
consumer.accept(this.applicationContext.getBean(clazz));
|
}
|
}
|
|
}
|