实践丨SpringBoot整合Mybatis-Plus项目存在Mapper时报错
摘要:在SpringBoot运行测试Mybatis-Plus测试的时候报错的问题分析与修复
本文分享自华为云社区《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整合Mybatis-Plus项目存在Mapper时报错的更多相关文章
- SpringBoot整合Mybatis之项目结构、数据源
已经有好些日子没有总结了,不是变懒了,而是我一直在奋力学习springboot的路上,现在也算是完成了第一阶段的学习,今天给各位总结总结. 之前在网上找过不少关于springboot的教程,都是一些比 ...
- springboot 测试类,项目使用shiro时报错UnavailableSecurityManagerException
大概的问题就是,正常运行项目是没有问题的 使用测试类是,加载不了shiro的securityManager,主要导致不是很清楚,望告知, 解决方法 @Resource org.apache.shiro ...
- springboot整合mybatis源码分析
springboot整合mybatis源码分析 本文主要讲述mybatis在springboot中是如何被加载执行的,由于涉及的内容会比较多,所以这次只会对调用关系及关键代码点进行讲解,为了避免文章太 ...
- springBoot 整合 mybatis 项目实战
二.springBoot 整合 mybatis 项目实战 前言 上一篇文章开始了我们的springboot序篇,我们配置了mysql数据库,但是我们sql语句直接写在controller中并且使用 ...
- 三、SpringBoot 整合mybatis 多数据源以及分库分表
前言 说实话,这章本来不打算讲的,因为配置多数据源的网上有很多类似的教程.但是最近因为项目要用到分库分表,所以让我研究一下看怎么实现.我想着上一篇博客讲了多环境的配置,不同的环境调用不同的数据库,那接 ...
- 【java框架】SpringBoot(7) -- SpringBoot整合MyBatis
1.整合MyBatis操作 前面一篇提到了SpringBoot整合基础的数据源JDBC.Druid操作,实际项目中更常用的还是MyBatis框架,而SpringBoot整合MyBatis进行CRUD也 ...
- SpringBoot整合Mybatis【非注解版】
接上文:SpringBoot整合Mybatis[注解版] 一.项目创建 新建一个工程 选择Spring Initializr,配置JDK版本 输入项目名 选择构建web项目所需的state ...
- springboot学习随笔(四):Springboot整合mybatis(含generator自动生成代码)
这章我们将通过springboot整合mybatis来操作数据库 以下内容分为两部分,一部分主要介绍generator自动生成代码,生成model.dao层接口.dao接口对应的sql配置文件 第一部 ...
- springBoot整合mybatis、jsp 或 HTML
springBoot整合mybatis.jsp Spring Boot的主要优点: 1: 为所有Spring开发者更快的入门: 2: 开箱即用,提供各种默认配置来简化项目配置: 3: 内嵌式容器 ...
随机推荐
- 07.并发编程Threads
参考文档 https://www.cnblogs.com/springsnow/p/9409205.html#_label0 1. 基础概念 1.1 进程/线程/多线程 进程(Process) 计算机 ...
- 【Azure 应用服务】应用代码需要客户端证书进行验证,部署到App Service后,如何配置让客户端携带证书呢?
问题描述 .NET 6 MVC应用,代码中要求客户端访问时候必须携带正确的证书,如果不携带或者携带错误的证书,都会得到 HTTP ERROR 403 Forbidden 错误 在App Service ...
- 模块和包—Day28
一.模块 模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. import的过程:import一个模块的时候,首先创建一个属于my_module的内存空间,加载my_ ...
- yum配置及使用命令
linux yum 命令 yum( Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器. 基於RPM包管理,能够从指 ...
- angular访问后台服务及监控会话超时的封装实现
以前一直没有想过写一些东西来把项目中用到的知识点及技术实现做一个归纳整理并分享出来.现在打算逐渐的把项目中的一些东西整理并分享出来,与大家共勉! angular本身自带访问组件http和httpcli ...
- DNS中的FQDN
FQDN:(Fully Qualified Domain Name)全限定域名:同时带有主机名和域名的名称.(通过符号".") 例如:主机名是bigserver,域名是mycomp ...
- 厌倦了excel绘制地图的繁琐操作,来看看这款可视化地图神器!
在现代生活中,地图无论对于社会主义建设.国防.运输以至旅行都是不可缺少的.要学会正确地使用地图,必须学会如何绘制地图. 最近我发现了一款好用的可视化地图神器,比excel做地图可视化好一万倍!其实呢, ...
- 【windows 访问控制】二、安全描述符(Security Descriptors,SD)
安全描述符(Security Descriptors,SD) 定义 安全描述符是与安全对象的安全信息,它含有这个对象所有者的SID,以及一个访问控制列表(ACL,Access Control List ...
- 每日一算法之two sum
题目如下:首先准备一个数组,[1,2,8,4,9] 然后输入一个6,找出数组两项之和为6的两个下标. 啥也不想,马上上代码,这个太简单了, static int[] twoSum(int[] num ...
- kubernetes配置使用ceph动态存储
在k8s集群中配置ceph 3.1.使用cephfs (1) 在ceph集群创建cephfs #以下操作在ceph集群的admin或者mon节点上执行 #创建pool来存储数据和元数据 ceph os ...