实践丨springboot整合mybatis-plus项目存在mapper时报错

华为云开发者社区      2022-04-27     270

关键词:

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

异常信息

  • 在SpringBoot运行测试Mybatis-Plus测试的时候报错:
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:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.baomidou.mybatisplus.spring.boot.starter;

import com.baomidou.mybatisplus.MybatisConfiguration;
import com.baomidou.mybatisplus.MybatisXMLLanguageDriver;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import java.util.Iterator;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
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.mybatis.spring.mapper.ClassPathMapperScanner;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

@Configuration
@ConditionalOnClass(SqlSessionFactory.class, MybatisSqlSessionFactoryBean.class)
@ConditionalOnBean(DataSource.class)
@EnableConfigurationProperties(MybatisPlusProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisPlusAutoConfiguration 
    private static final Log logger = LogFactory.getLog(MybatisPlusAutoConfiguration.class);
    private final MybatisPlusProperties properties;
    private final Interceptor[] interceptors;
    private final ResourceLoader resourceLoader;
    private final DatabaseIdProvider databaseIdProvider;
    private final List<ConfigurationCustomizer> configurationCustomizers;

    public MybatisPlusAutoConfiguration(MybatisPlusProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider, ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> databaseIdProvider, ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) 
        this.properties = properties;
        this.interceptors = (Interceptor[])interceptorsProvider.getIfAvailable();
        this.resourceLoader = resourceLoader;
        this.databaseIdProvider = (DatabaseIdProvider)databaseIdProvider.getIfAvailable();
        this.configurationCustomizers = (List)configurationCustomizersProvider.getIfAvailable();
    

    @PostConstruct
    public void checkConfigFileExists() 
        if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) 
            Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());
            Assert.state(resource.exists(), "Cannot find config location: " + resource + " (please add config file or check your Mybatis configuration)");
        

    

    @Bean
    @ConditionalOnMissingBean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception 
        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()));
        

        MybatisConfiguration configuration = this.properties.getConfiguration();
        if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) 
            configuration = new MybatisConfiguration();
        

        if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) 
            Iterator i$ = this.configurationCustomizers.iterator();

            while(i$.hasNext()) 
                ConfigurationCustomizer customizer = (ConfigurationCustomizer)i$.next();
                customizer.customize(configuration);
            
        

        configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
        factory.setConfiguration(configuration);
        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 (StringUtils.hasLength(this.properties.getTypeEnumsPackage())) 
            factory.setTypeEnumsPackage(this.properties.getTypeEnumsPackage());
        

        if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) 
            factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
        

        if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) 
            factory.setMapperLocations(this.properties.resolveMapperLocations());
        

        if (!ObjectUtils.isEmpty(this.properties.getGlobalConfig())) 
            factory.setGlobalConfig(this.properties.getGlobalConfig().convertGlobalConfiguration());
        

        return factory.getObject();
    

    @Bean
    @ConditionalOnMissingBean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) 
        ExecutorType executorType = this.properties.getExecutorType();
        return executorType != null ? new SqlSessionTemplate(sqlSessionFactory, executorType) : new SqlSessionTemplate(sqlSessionFactory);
    

    @Configuration
    @Import(MybatisPlusAutoConfiguration.AutoConfiguredMapperScannerRegistrar.class)
    @ConditionalOnMissingBean(MapperFactoryBean.class)
    public static class MapperScannerRegistrarNotFoundConfiguration 
        public MapperScannerRegistrarNotFoundConfiguration() 
        

        @PostConstruct
        public void afterPropertiesSet() 
            MybatisPlusAutoConfiguration.logger.debug("No " + MapperFactoryBean.class.getName() + " found.");
        
    

    public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware 
        private BeanFactory beanFactory;
        private ResourceLoader resourceLoader;

        public AutoConfiguredMapperScannerRegistrar() 
        

        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) 
            MybatisPlusAutoConfiguration.logger.debug("Searching for mappers annotated with @Mapper");
            ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);

            try 
                if (this.resourceLoader != null) 
                    scanner.setResourceLoader(this.resourceLoader);
                

                List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
                if (MybatisPlusAutoConfiguration.logger.isDebugEnabled()) 
                    Iterator i$ = packages.iterator();

                    while(i$.hasNext()) 
                        String pkg = (String)i$.next();
                        MybatisPlusAutoConfiguration.logger.debug("Using auto-configuration base package '" + pkg + "'");
                    
                

                scanner.setAnnotationClass(Mapper.class);
                scanner.registerFilters();
                scanner.doScan(StringUtils.toStringArray(packages));
             catch (IllegalStateException var7) 
                MybatisPlusAutoConfiguration.logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled." + var7);
            

        

        public void setBeanFactory(BeanFactory beanFactory) throws BeansException 
            this.beanFactory = beanFactory;
        

        public void setResourceLoader(ResourceLoader resourceLoader) 
            this.resourceLoader = resourceLoader;
        
    

解决办法

@Mapper

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

@MapperScan

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

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

springboot整合dubbo-服务化最佳实践

分包:公共的模型、接口、异常都放在此处(springboot-interface-api)将springboot-meeting-service、springboot-user-service系统pojo和service提取到springboot-interface-api1.分包——新建普通maven项目      springboot 查看详情

springboot与mybatis整合最佳实践

前言:Springboot怎么使用想必也无需我多言,Mybitas作为实用性极强的ORM框架也深受广大开发人员喜爱,有关如何整合它们的文章在网络上随处可见。但是今天我会从实战的角度出发,谈谈我对二者结合与使用的最佳实践。一、依... 查看详情

springboot整合redis初实践

  Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。  有时,为了提升整个网站的性能,在开发时会将经常访问的数据进行缓存,这样在调用这个数据接口时,可以提高数据加载... 查看详情

springboot+openjpa整合gbase8s实践(代码片段)

...A之间的关系,然后通过一个手把手的应用案例来讲述Springboot和Openjpa整合GBase8s。那么就让我们开始吧。JPAJPA(JavaPersistenceAPI)作为JavaEE5.0平台标准的ORM规范,将得到所有JavaEE服务器的支持。Sun这次吸取了之前EJB规范惨痛失... 查看详情

springboot整合easyexcel(代码片段)

文章目录SpringBoot整合EasyExcel1.EasyExcel简介2.使用EasyExcel实现写2.1创建实体类2.2测试写Excel3.使用EasyExcel实现读3.1创建读取操作的监听器3.2测试读Excel4.springboot项目实践EasyExcel4.1pom中引入相关依赖4.2创建数据库表及添加数据4.3实体类4... 查看详情

重学springboot系列之整合数据库开发框架---中(代码片段)

重学Springboot系列之整合数据库开发框架---中javabean的赋值转换为什么要做javabean赋值转换BeanUtils和Dozer?引入Dozer(6.2.0)自定义类型转换(非对称类型转换)映射localDateTime的问题整合MybatisGenerator操作数据整合M... 查看详情

springboot+openjpa整合gbase8s实践(代码片段)

...A之间的关系,然后通过一个手把手的应用案例来讲述Springboot和Openjpa整合GBase8s。那么就让我们开始吧。JPAJPA(JavaPersistenceAPI)作为JavaEE5.0平台标准的ORM规范,将得到所有JavaEE服务器的支持。Sun这次吸取了之前EJB规范惨痛失... 查看详情

springboot+openjpa整合gbase8s实践(代码片段)

...A之间的关系,然后通过一个手把手的应用案例来讲述Springboot和Openjpa整合GBase8s。那么就让我们开始吧。JPAJPA(JavaPersistenceAPI)作为JavaEE5.0平台标准的ORM规范,将得到所有JavaEE服务器的支持。Sun这次吸取了之前EJB规范惨痛失... 查看详情

springboot2.0整合fastjson的正确姿势(代码片段)

    SpringBoot2.0如何集成fastjson?在网上查了一堆资料,但是各文章的说法不一,有些还是错的,可能只是简单测试一下就认为ok了,最后有没生效都不知道。恰逢公司项目需要将JackSon换成fastjson,因此自己来实践一... 查看详情

springboot2+springsecurity+cas整合认证(代码片段)

...最后一步,实践检验真理的最后一步9.结束语1.前言下面SpringBoot2+SpringSecurity+CAS安全认证整合项目2.pom.xml<?xmlversion="1.0"e 查看详情

springboot2.x最佳实践《一》之springboot2.x初体验

SpringBoot2.X最佳实践前言本系列文章,从零基础接触 SpringBoot2.x新版本,基础入门使用,热部署,到整合各个主流框架Redis4.x,消息队列AciveMQ,RocketMQ等,搜索框架ElasticSearch5.6版本,到web-flux反应式编程,到Actuator监控应用信息... 查看详情

springboot项目整合redis

👏👏👏哈喽!大家好,我是【学无止境小奇】,一位热爱分享各种技术的博主!😍😍😍⭐【学无止境小奇】的创作宗旨:每一条命令都亲自执行过,每一行代码都实际运行过࿰... 查看详情

springboot整合邮件服务(代码片段)

参考教程首先参考了SpringBoot整合邮件配置,这篇文章写的很好,按照上面的操作一步步走下去就行了。遇到的问题版本配置然后因为反复配置版本很麻烦,所以参考了如何统一引入SpringBoot版本?。FreeMarker在配置FreeMarker时,发... 查看详情

实践丨rabbitmq通过shovel插件迁移数据

前言生产环境中会遇到RabbitMQ数据迁移的场景,例如:切换云服务厂商、不同Region之间数据迁移、新搭建RabbitMQ实例,数据需要同步至新的RabbitMQ实例。前提条件:源RabbitMQ实例打开了shovel插件。目的RabbitMQ实例打开了shovel插件。... 查看详情

[springboot系列]springboot如何整合ssmp

文章目录基于SpringBoot实现SSMP整合基于SpringBoot实现SSMP整合SpringBoot之所以好用,就是它能方便快捷的整合其他技术,这里我们先介绍四种技术的整合:整合JUnit整合MyBatis整合MyBatis-Plus整合Druid整合JUnitSpringBoot技术的定位用于简化... 查看详情

springboot整合easyexcel(代码片段)

文章目录SpringBoot整合EasyExcel1.EasyExcel简介2.使用EasyExcel实现写2.1创建实体类2.2测试写Excel3.使用EasyExcel实现读3.1创建读取操作的监听器3.2测试读Excel4.springboot项目实践EasyExcel4.1pom中引入相关依赖4.2创建数据库表及添加数据4.3实体类4... 查看详情

springboot完成ssm整合之springboot整合junit(代码片段)

SpringBoot🍌掌握基于SpringBoot框架的程序开发步骤🍌使用SpringBoot配置信息修改服务器配置今日目标:基于SpringBoot的完成SSM整合项目开发第一步一、SpringBoot整合junit回顾Spring整合junit@RunWith(SpringJUnit4ClassRunner.class)@C... 查看详情

开发实践丨昇腾cann的推理应用开发体验

摘要:这是关于一次Ascend在线实验的记录,主要内容是通过网络模型加载、推理、结果输出的部署全流程展示,从而快速熟悉并掌握ACL(AscendComputingLanguage)基本开发流程。本文分享自华为云社区《​​基于昇腾CANN的推理应用开... 查看详情