您好,登錄后才能下訂單哦!
這篇文章主要介紹了MybatisPlus整合Flowable出現錯誤怎么解決的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇MybatisPlus整合Flowable出現錯誤怎么解決文章都會有所收獲,下面我們一起來看看吧。
Description:
file [D:\project\carshow-server\server-flowable\flowable-admin\target\classes\com\carshow\flowable\mapper\IFlowableCommentMapper.class] required a single bean, but 2 were found:
- sqlSessionFactory: defined by method 'sqlSessionFactory' in class path resource [com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.class]
- modelerSqlSessionFactory: defined by method 'modelerSqlSessionFactory' in class path resource [org/flowable/ui/modeler/conf/ModelerDatabaseConfiguration.class]
Action:Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
整合的bean沖突,spring找到了兩個
MybatisPlus: MybatisPlusAutoConfiguration.class
Flowable:ModelerDatabaseConfiguration.class
@ConditionalOnMissingBean:它是修飾bean的一個注解,主要實現的是,當你的bean被注冊之后,如果有注冊相同類型的bean,就不會成功,它會保證你的bean只有一個,即你的實例只有一個,當你注冊多個相同的bean時,會出現異常,以此來告訴開發人員。
1. 環境:Flowable6.6
2. 解決:
重寫mybatis-plus 自動配置類(由于 flowable-modeler 引入時候,會初始化 mybatis的Template和SqlFactory,這導致 mybatis-plus 本身的autoconfig 無法生效,所以需要重寫),從源碼中拆寫代碼:
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties; 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.injector.ISqlInjector; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; import org.apache.ibatis.mapping.DatabaseIdProvider; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.context.ApplicationContext; import org.springframework.core.io.ResourceLoader; import org.springframework.util.StringUtils; import javax.sql.DataSource; import java.util.List; /** * @author xw * @description 重寫mybatis-plus 自動配置類 * @date 2022/1/7 14:06 */ public class AbstractMybatisPlusConfiguration { protected SqlSessionFactory getSqlSessionFactory( DataSource dataSource, MybatisPlusProperties properties, ResourceLoader resourceLoader, Interceptor[] interceptors, DatabaseIdProvider databaseIdProvider, ApplicationContext applicationContext ) throws Exception { 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); if (properties.getConfigurationProperties() != null) { factory.setConfigurationProperties(properties.getConfigurationProperties()); } if (!ObjectUtils.isEmpty(interceptors)) { factory.setPlugins(interceptors); } if (databaseIdProvider != null) { factory.setDatabaseIdProvider(databaseIdProvider); } if (StringUtils.hasLength(properties.getTypeAliasesPackage())) { factory.setTypeAliasesPackage(properties.getTypeAliasesPackage()); } // TODO 自定義枚舉包 if (StringUtils.hasLength(properties.getTypeEnumsPackage())) { factory.setTypeEnumsPackage(properties.getTypeEnumsPackage()); } if (properties.getTypeAliasesSuperType() != null) { factory.setTypeAliasesSuperType(properties.getTypeAliasesSuperType()); } if (StringUtils.hasLength(properties.getTypeHandlersPackage())) { factory.setTypeHandlersPackage(properties.getTypeHandlersPackage()); } if (!ObjectUtils.isEmpty(properties.resolveMapperLocations())) { factory.setMapperLocations(properties.resolveMapperLocations()); } // TODO 此處必為非 NULL 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 keyGenerator = applicationContext.getBean(IKeyGenerator.class); globalConfig.getDbConfig().setKeyGenerators((List<IKeyGenerator>) keyGenerator); } //注入sql注入器 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) { MybatisConfiguration configuration = properties.getConfiguration(); if (configuration == null && !StringUtils.hasText(properties.getConfigLocation())) { configuration = new MybatisConfiguration(); } // if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) { // for (ConfigurationCustomizer customizer : this.configurationCustomizers) { // customizer.customize(configuration); // } // } factory.setConfiguration(configuration); } public SqlSessionTemplate getSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, MybatisPlusProperties properties) { ExecutorType executorType = properties.getExecutorType(); if (executorType != null) { return new SqlSessionTemplate(sqlSessionFactory, executorType); } else { return new SqlSessionTemplate(sqlSessionFactory); } } }
繼承重寫的配置類
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ResourceLoader; import javax.sql.DataSource; /** * @author xw * @description * @date 2022/1/7 16:24 */ @MapperScan( sqlSessionTemplateRef = "mySqlSessionTemplate", sqlSessionFactoryRef = "mySqlSessionFactory" ) @EnableConfigurationProperties(MybatisPlusProperties.class) @Configuration public class MybatisPlusConfiguration extends AbstractMybatisPlusConfiguration { @Bean(name = "mySqlSessionFactory") public SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource, MybatisPlusProperties properties, ResourceLoader resourceLoader, ApplicationContext applicationContext) throws Exception { return getSqlSessionFactory(dataSource, properties, resourceLoader, null, null, applicationContext); } @Bean(name = "mySqlSessionTemplate") public SqlSessionTemplate sqlSessionTemplate(MybatisPlusProperties properties, @Qualifier("mySqlSessionFactory") SqlSessionFactory sqlSessionFactory) { return getSqlSessionTemplate(sqlSessionFactory, properties); } }
重寫 flowable-modeler 中 ModelerDatabaseConfiguration,用 @Primary 指定框架內部的mybatis 作為默認的
import liquibase.Liquibase; import liquibase.database.Database; import liquibase.database.DatabaseConnection; import liquibase.database.DatabaseFactory; import liquibase.database.jvm.JdbcConnection; import liquibase.exception.DatabaseException; import liquibase.resource.ClassLoaderResourceAccessor; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.session.SqlSessionFactory; import org.flowable.common.engine.api.FlowableException; import org.flowable.ui.common.service.exception.InternalServerErrorException; import org.flowable.ui.modeler.properties.FlowableModelerAppProperties; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.support.ResourcePatternUtils; import javax.sql.DataSource; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.SQLException; import java.util.Properties; /** * @author xw * @description 重寫 flowable-modeler 中 ModelerDatabaseConfiguration * @date 2022/1/7 16:31 */ @Configuration @Slf4j public class DatabaseConfiguration { protected static final String LIQUIBASE_CHANGELOG_PREFIX = "ACT_DE_"; @Autowired protected FlowableModelerAppProperties modelerAppProperties; @Autowired protected ResourceLoader resourceLoader; protected static Properties databaseTypeMappings = getDefaultDatabaseTypeMappings(); public static final String DATABASE_TYPE_H2 = "h3"; public static final String DATABASE_TYPE_HSQL = "hsql"; public static final String DATABASE_TYPE_MYSQL = "mysql"; public static final String DATABASE_TYPE_ORACLE = "oracle"; public static final String DATABASE_TYPE_POSTGRES = "postgres"; public static final String DATABASE_TYPE_MSSQL = "mssql"; public static final String DATABASE_TYPE_DB2 = "db2"; public static Properties getDefaultDatabaseTypeMappings() { Properties databaseTypeMappings = new Properties(); databaseTypeMappings.setProperty("H2", DATABASE_TYPE_H2); databaseTypeMappings.setProperty("HSQL Database Engine", DATABASE_TYPE_HSQL); databaseTypeMappings.setProperty("MySQL", DATABASE_TYPE_MYSQL); databaseTypeMappings.setProperty("Oracle", DATABASE_TYPE_ORACLE); databaseTypeMappings.setProperty("PostgreSQL", DATABASE_TYPE_POSTGRES); databaseTypeMappings.setProperty("Microsoft SQL Server", DATABASE_TYPE_MSSQL); databaseTypeMappings.setProperty(DATABASE_TYPE_DB2, DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/NT", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/NT64", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2 UDP", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/LINUX", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/LINUX390", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/LINUXX8664", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/LINUXZ64", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/LINUXPPC64", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/400 SQL", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/6000", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2 UDB iSeries", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/AIX64", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/HPUX", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/HP64", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/SUN", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/SUN64", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/PTX", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2/2", DATABASE_TYPE_DB2); databaseTypeMappings.setProperty("DB2 UDB AS400", DATABASE_TYPE_DB2); return databaseTypeMappings; } @Bean @Primary public SqlSessionFactory sqlSessionFactory(DataSource dataSource) { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource); String databaseType = initDatabaseType(dataSource); if (databaseType == null) { throw new FlowableException("couldn't deduct database type"); } try { Properties properties = new Properties(); properties.put("prefix", modelerAppProperties.getDataSourcePrefix()); properties.put("blobType", "BLOB"); properties.put("boolValue", "TRUE"); properties.load(this.getClass().getClassLoader().getResourceAsStream("org/flowable/db/properties/" + databaseType + ".properties")); sqlSessionFactoryBean.setConfigurationProperties(properties); sqlSessionFactoryBean .setMapperLocations(ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources("classpath:/META-INF/modeler-mybatis-mappings/*.xml")); sqlSessionFactoryBean.afterPropertiesSet(); return sqlSessionFactoryBean.getObject(); } catch (Exception e) { throw new FlowableException("Could not create sqlSessionFactory", e); } } @Primary @Bean(destroyMethod = "clearCache") // destroyMethod: see https://github.com/mybatis/old-google-code-issues/issues/778 public SqlSessionTemplate SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } @Bean public Liquibase liquibase(DataSource dataSource) { log.info("Configuring Liquibase"); Liquibase liquibase = null; try { DatabaseConnection connection = new JdbcConnection(dataSource.getConnection()); Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(connection); database.setDatabaseChangeLogTableName(LIQUIBASE_CHANGELOG_PREFIX + database.getDatabaseChangeLogTableName()); database.setDatabaseChangeLogLockTableName(LIQUIBASE_CHANGELOG_PREFIX + database.getDatabaseChangeLogLockTableName()); liquibase = new Liquibase("META-INF/liquibase/flowable-modeler-app-db-changelog.xml", new ClassLoaderResourceAccessor(), database); liquibase.update("flowable"); return liquibase; } catch (Exception e) { throw new InternalServerErrorException("Error creating liquibase database", e); } finally { closeDatabase(liquibase); } } protected String initDatabaseType(DataSource dataSource) { String databaseType = null; Connection connection = null; try { connection = dataSource.getConnection(); DatabaseMetaData databaseMetaData = connection.getMetaData(); String databaseProductName = databaseMetaData.getDatabaseProductName(); log.info("database product name: '{}'", databaseProductName); databaseType = databaseTypeMappings.getProperty(databaseProductName); if (databaseType == null) { throw new FlowableException("couldn't deduct database type from database product name '" + databaseProductName + "'"); } log.info("using database type: {}", databaseType); } catch (SQLException e) { log.error("Exception while initializing Database connection", e); } finally { try { if (connection != null) { connection.close(); } } catch (SQLException e) { log.error("Exception while closing the Database connection", e); } } return databaseType; } private void closeDatabase(Liquibase liquibase) { if (liquibase != null) { Database database = liquibase.getDatabase(); if (database != null) { try { database.close(); } catch (DatabaseException e) { log.warn("Error closing database", e); } } } } }
關于“MybatisPlus整合Flowable出現錯誤怎么解決”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“MybatisPlus整合Flowable出現錯誤怎么解決”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。