实践丨SpringBoot整合Mybatis-Plus项目存在Mapper时报错

x33g5p2x  于2022-03-25 转载在 Spring  
字(8.7k)|赞(0)|评价(0)|浏览(411)

本文分享自华为云社区《SpringBoot整合MybatisPlus项目存在Mapper时运行报错的问题分析与修复》,作者:攻城狮Chova 。

异常信息

  • 在SpringBoot运行测试Mybatis-Plus测试的时候报错:
  1. rg.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.oxford.test.ApplicationTests':

原因

  • 自定义的mapper文件不受Spring管理所以不会注入到Spring容器中

  • mybatis-config中只是会为对应的mapper创建代理类

  • 想真正包装成bean, 注入到spring容器中,需要使用到AutoConfiguredMapperScannerRegistrar它会根据扫描 @Mapper注释或是 @MapperScan指定的包下的接口,将其注册为bean

  • AutoConfiguredMapperScannerRegistrar:

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. package com.baomidou.mybatisplus.spring.boot.starter;
  6. import com.baomidou.mybatisplus.MybatisConfiguration;
  7. import com.baomidou.mybatisplus.MybatisXMLLanguageDriver;
  8. import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
  9. import java.util.Iterator;
  10. import java.util.List;
  11. import javax.annotation.PostConstruct;
  12. import javax.sql.DataSource;
  13. import org.apache.ibatis.annotations.Mapper;
  14. import org.apache.ibatis.logging.Log;
  15. import org.apache.ibatis.logging.LogFactory;
  16. import org.apache.ibatis.mapping.DatabaseIdProvider;
  17. import org.apache.ibatis.plugin.Interceptor;
  18. import org.apache.ibatis.session.ExecutorType;
  19. import org.apache.ibatis.session.SqlSessionFactory;
  20. import org.mybatis.spring.SqlSessionTemplate;
  21. import org.mybatis.spring.mapper.ClassPathMapperScanner;
  22. import org.mybatis.spring.mapper.MapperFactoryBean;
  23. import org.springframework.beans.BeansException;
  24. import org.springframework.beans.factory.BeanFactory;
  25. import org.springframework.beans.factory.BeanFactoryAware;
  26. import org.springframework.beans.factory.ObjectProvider;
  27. import org.springframework.beans.factory.support.BeanDefinitionRegistry;
  28. import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
  29. import org.springframework.boot.autoconfigure.AutoConfigureAfter;
  30. import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
  31. import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  32. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
  33. import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  34. import org.springframework.boot.context.properties.EnableConfigurationProperties;
  35. import org.springframework.context.ResourceLoaderAware;
  36. import org.springframework.context.annotation.Bean;
  37. import org.springframework.context.annotation.Configuration;
  38. import org.springframework.context.annotation.Import;
  39. import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
  40. import org.springframework.core.io.Resource;
  41. import org.springframework.core.io.ResourceLoader;
  42. import org.springframework.core.type.AnnotationMetadata;
  43. import org.springframework.util.Assert;
  44. import org.springframework.util.CollectionUtils;
  45. import org.springframework.util.ObjectUtils;
  46. import org.springframework.util.StringUtils;
  47. @Configuration
  48. @ConditionalOnClass({SqlSessionFactory.class, MybatisSqlSessionFactoryBean.class})
  49. @ConditionalOnBean({DataSource.class})
  50. @EnableConfigurationProperties({MybatisPlusProperties.class})
  51. @AutoConfigureAfter({DataSourceAutoConfiguration.class})
  52. public class MybatisPlusAutoConfiguration {
  53. private static final Log logger = LogFactory.getLog(MybatisPlusAutoConfiguration.class);
  54. private final MybatisPlusProperties properties;
  55. private final Interceptor[] interceptors;
  56. private final ResourceLoader resourceLoader;
  57. private final DatabaseIdProvider databaseIdProvider;
  58. private final List<ConfigurationCustomizer> configurationCustomizers;
  59. public MybatisPlusAutoConfiguration(MybatisPlusProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider, ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> databaseIdProvider, ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) {
  60. this.properties = properties;
  61. this.interceptors = (Interceptor[])interceptorsProvider.getIfAvailable();
  62. this.resourceLoader = resourceLoader;
  63. this.databaseIdProvider = (DatabaseIdProvider)databaseIdProvider.getIfAvailable();
  64. this.configurationCustomizers = (List)configurationCustomizersProvider.getIfAvailable();
  65. }
  66. @PostConstruct
  67. public void checkConfigFileExists() {
  68. if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {
  69. Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());
  70. Assert.state(resource.exists(), "Cannot find config location: " + resource + " (please add config file or check your Mybatis configuration)");
  71. }
  72. }
  73. @Bean
  74. @ConditionalOnMissingBean
  75. public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
  76. MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
  77. factory.setDataSource(dataSource);
  78. factory.setVfs(SpringBootVFS.class);
  79. if (StringUtils.hasText(this.properties.getConfigLocation())) {
  80. factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
  81. }
  82. MybatisConfiguration configuration = this.properties.getConfiguration();
  83. if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
  84. configuration = new MybatisConfiguration();
  85. }
  86. if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
  87. Iterator i$ = this.configurationCustomizers.iterator();
  88. while(i$.hasNext()) {
  89. ConfigurationCustomizer customizer = (ConfigurationCustomizer)i$.next();
  90. customizer.customize(configuration);
  91. }
  92. }
  93. configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
  94. factory.setConfiguration(configuration);
  95. if (this.properties.getConfigurationProperties() != null) {
  96. factory.setConfigurationProperties(this.properties.getConfigurationProperties());
  97. }
  98. if (!ObjectUtils.isEmpty(this.interceptors)) {
  99. factory.setPlugins(this.interceptors);
  100. }
  101. if (this.databaseIdProvider != null) {
  102. factory.setDatabaseIdProvider(this.databaseIdProvider);
  103. }
  104. if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
  105. factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
  106. }
  107. if (StringUtils.hasLength(this.properties.getTypeEnumsPackage())) {
  108. factory.setTypeEnumsPackage(this.properties.getTypeEnumsPackage());
  109. }
  110. if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
  111. factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
  112. }
  113. if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
  114. factory.setMapperLocations(this.properties.resolveMapperLocations());
  115. }
  116. if (!ObjectUtils.isEmpty(this.properties.getGlobalConfig())) {
  117. factory.setGlobalConfig(this.properties.getGlobalConfig().convertGlobalConfiguration());
  118. }
  119. return factory.getObject();
  120. }
  121. @Bean
  122. @ConditionalOnMissingBean
  123. public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
  124. ExecutorType executorType = this.properties.getExecutorType();
  125. return executorType != null ? new SqlSessionTemplate(sqlSessionFactory, executorType) : new SqlSessionTemplate(sqlSessionFactory);
  126. }
  127. @Configuration
  128. @Import({MybatisPlusAutoConfiguration.AutoConfiguredMapperScannerRegistrar.class})
  129. @ConditionalOnMissingBean({MapperFactoryBean.class})
  130. public static class MapperScannerRegistrarNotFoundConfiguration {
  131. public MapperScannerRegistrarNotFoundConfiguration() {
  132. }
  133. @PostConstruct
  134. public void afterPropertiesSet() {
  135. MybatisPlusAutoConfiguration.logger.debug("No " + MapperFactoryBean.class.getName() + " found.");
  136. }
  137. }
  138. public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware {
  139. private BeanFactory beanFactory;
  140. private ResourceLoader resourceLoader;
  141. public AutoConfiguredMapperScannerRegistrar() {
  142. }
  143. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  144. MybatisPlusAutoConfiguration.logger.debug("Searching for mappers annotated with @Mapper");
  145. ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
  146. try {
  147. if (this.resourceLoader != null) {
  148. scanner.setResourceLoader(this.resourceLoader);
  149. }
  150. List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
  151. if (MybatisPlusAutoConfiguration.logger.isDebugEnabled()) {
  152. Iterator i$ = packages.iterator();
  153. while(i$.hasNext()) {
  154. String pkg = (String)i$.next();
  155. MybatisPlusAutoConfiguration.logger.debug("Using auto-configuration base package '" + pkg + "'");
  156. }
  157. }
  158. scanner.setAnnotationClass(Mapper.class);
  159. scanner.registerFilters();
  160. scanner.doScan(StringUtils.toStringArray(packages));
  161. } catch (IllegalStateException var7) {
  162. MybatisPlusAutoConfiguration.logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled." + var7);
  163. }
  164. }
  165. public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
  166. this.beanFactory = beanFactory;
  167. }
  168. public void setResourceLoader(ResourceLoader resourceLoader) {
  169. this.resourceLoader = resourceLoader;
  170. }
  171. }
  172. }

解决办法

@Mapper

  • mapper文件的类上添加 @Mapper注解

@MapperScan

  • 在主类上添加 @MapperScan注解,指定mapper的扫描范围,注意值为mapper文件所在的包名
  1. @MapperScan("com.oxford.mapper")

点击关注,第一时间了解华为云新鲜技术~​

相关文章