SpringBoot下使用tk.mapper遇到的小坑

本文记录了在SpringBoot项目中使用tk.mapper时遇到的bean注入问题,详细描述了从错误日志分析、模块结构排查到最后发现启动类目录配置不当导致MapperConfig未生效的解决过程,提醒开发者注意模块依赖及启动类位置对配置扫描的影响。

前言:在使用同事封装的自定义通用mapper接口工具模块时,出现扫描不到业务模块的mapper接口报出控制器、服务实现类依赖无法满足问题。

错误类似以下内容(当时并没有保存日志):

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘userController’: Unsatisfied dependency expressed through field ‘userMapper’; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ‘com.minibike.bike.user.dao.UserMapper’ available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}”

1.从日志得到的信息

控制器、服务实现类的依赖无法满足是因为UserMapper这个bean没有被注入(可以从该句看出:expected at least 1 bean which qualifies as autowire candidate.)

2.大致的分析

既然UserMapper这个bean没有被装配成功,那么问题可能出现在Mapper包的扫描上。(mapper包

Caused by: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.farmer.region.mapper.RegionMapper.selectValidCityCode at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:229) at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:53) at org.apache.ibatis.binding.MapperProxy.lambda$cachedInvoker$0(MapperProxy.java:96) at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) at org.apache.ibatis.util.MapUtil.computeIfAbsent(MapUtil.java:36) at org.apache.ibatis.binding.MapperProxy.cachedInvoker(MapperProxy.java:94) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86) at com.sun.proxy.$Proxy277.selectValidCityCode(Unknown Source) at com.farmer.region.service.impl.RegionServiceImpl.loadValidCityCode(RegionServiceImpl.java:196) at com.farmer.region.service.impl.RegionServiceImpl.init(RegionServiceImpl.java:191) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) ... 46 common frames omitted
08-09
<think> 我们面对的问题是:Invalid bound statement (not found): com.atguigu.springboot_ssm1.mapper.EmpMapper.selectAll 根据引用内容,这个问题通常是由于Mapper接口与对应的XML文件绑定失败导致的。可能的原因包括: 1. XML文件没有正确放置在类路径下(如resources目录),导致编译时没有被复制到target目录。 2. Mapper接口与XML文件的命名不一致(例如,接口名为EmpMapper,XML文件应为EmpMapper.xml)。 3. 在配置文件中(如spring-context.xml或application.properties)没有正确指定mapperLocations。 4. 如果使用了Maven,可能没有配置资源过滤,导致XML文件在打包时没有被包含。 根据引用[3]、[4]、[5]提供的解决方案,我们可以从以下几个方面进行排查: 步骤1:检查XML文件的位置和命名 - 确保EmpMapper.xml文件存在,并且其名称与接口名称一致(即EmpMapper.xml)。 - XML文件应该放置在正确的目录下。如果采用Maven项目结构,通常有两种方式: a) 放在src/main/resources目录下,并建立与接口包名相同的目录结构(如com/atguigu/springboot_ssm1/mapper)。 b) 放在src/main/java的对应包目录下,但需要在pom.xml中配置资源包含(因为默认情况下,Maven只打包resources目录下的资源文件)。 步骤2:检查XML文件中的namespace和id - 打开EmpMapper.xml文件,确保namespace属性是Mapper接口的全限定名(com.atguigu.springboot_ssm1.mapper.EmpMapper)。 - 确保有一个id为"selectAll"的SQL语句(如<select id="selectAll" ...>)。 步骤3:检查MyBatis配置 - 在Spring配置文件中(如spring-context.xml)检查SqlSessionFactoryBean的配置,尤其是mapperLocations属性,确保它能够扫描到XML文件。 例如: <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mapperLocations" value="classpath*:com/atguigu/springboot_ssm1/mapper/*.xml" /> <!-- 其他配置 --> </bean> - 如果使用注解配置,确保在配置类中指定了mapperLocations。 步骤4:Maven资源过滤配置(如果XML文件放在src/main/java目录下) - 在pom.xml中,添加资源目录配置,使得src/main/java下的xml文件也被包含在构建中。参考引用[4]和[5]: <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> </resource> <!-- 如果XML文件放在src/main/java下,添加以下配置 --> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> </build> 步骤5:检查编译后的target目录 - 构建项目后,检查target目录(如target/classes)下是否生成了EmpMapper.xml文件。路径应该是:target/classes/com/atguigu/springboot_ssm1/mapper/EmpMapper.xml。 - 如果没有,说明资源文件没有被正确复制,需要检查上述步骤。 步骤6:检查MyBatis-Spring的配置 - 确保在Spring配置中扫描了Mapper接口,例如使用<mybatis:scan>或@MapperScan注解。 @MapperScan("com.atguigu.springboot_ssm1.mapper") 或者在XML中配置: <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.atguigu.springboot_ssm1.mapper" /> </bean> 步骤7:检查依赖 - 确保MyBatis和MyBatis-Spring的版本兼容,且依赖正确。 按照以上步骤排查,通常可以解决该问题。 相关问题: 1. 如何配置MyBatis的mapperLocations? 2. Maven项目如何包含src/main/java下的资源文件? 3. 如何检查MyBatis的SQL映射文件是否正确绑定接口? </think> ### 解决 "Invalid bound statement (not found)" 错误的方法 该错误表明 MyBatis 无法找到 `EmpMapper.selectAll` 方法对应的 SQL 映射配置。以下是系统排查步骤: #### 1. **检查 XML 文件位置与命名规范** - **Mapper 接口路径**: `com.atguigu.springboot_ssm1.mapper.EmpMapper` - **对应 XML 文件路径**: - 若 XML 在 `src/main/resources` 下: `resources/com/atguigu/springboot_ssm1/mapper/EmpMapper.xml` - 若 XML 在 `src/main/java` 下: `java/com/atguigu/springboot_ssm1/mapper/EmpMapper.xml` - **命名规范**: XML 文件名必须与接口名**完全相同**(如 `EmpMapper.xml`)。 #### 2. **验证 XML 文件内容** 确保 `EmpMapper.xml` 包含以下关键配置: ```xml <mapper namespace="com.atguigu.springboot_ssm1.mapper.EmpMapper"> <select id="selectAll" resultType="com.atguigu.springboot_ssm1.entity.Emp"> SELECT * FROM emp_table </select> </mapper> ``` - `namespace`: 必须匹配**Mapper 接口的全限定名**。 - `id="selectAll"`: 必须与接口方法名**严格一致**。 #### 3. **Maven 资源过滤配置(关键步骤)** 在 `pom.xml` 中添加资源包含规则,确保 XML 文件被编译到 `target/classes`: ```xml <build> <resources> <!-- 包含 resources 目录下的 XML --> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> </includes> </resource> <!-- 包含 java 目录下的 XML(如有) --> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> </build> ``` > 引用[4][5]表明,Maven 默认不打包 `src/main/java` 下的非 `.java` 文件,需显式声明[^4][^5]。 #### 4. **检查 MyBatis 配置文件** 在 `application.properties` 或 `SqlSessionFactory` 配置中指定 XML 扫描路径: ```properties # application.properties 配置示例 mybatis.mapper-locations=classpath*:com/atguigu/springboot_ssm1/mapper/*.xml ``` > 引用[3]提到需在 `spring-context.xml` 中配置 `mapperLocations` 属性[^3]。 #### 5. **验证编译结果** 编译后检查 `target/classes` 目录: - 路径 `target/classes/com/atguigu/springboot_ssm1/mapper/` 下必须有 `EmpMapper.xml` 文件。 - 若文件缺失,说明 Maven 未正确打包资源。 #### 6. **其他排查点** - **注解冲突**: 确保接口方法未使用 `@Select` 等注解(避免与 XML 冲突)。 - **包扫描配置**: 在 Spring Boot 启动类添加 `@MapperScan`: ```java @MapperScan("com.atguigu.springboot_ssm1.mapper") @SpringBootApplication public class Application { ... } ``` - **文件编码**: 检查 XML 文件编码是否为 UTF-8(避免特殊字符解析错误)。 --- ### 总结流程 ```mermaid graph TD A[报错: Invalid bound statement] --> B[检查XML路径/命名] B --> C{XML是否存在且规范?} C -->|否| D[修正路径或命名] C -->|是| E[配置Maven资源过滤] E --> F[检查编译后target目录] F --> G{XML在target中?} G -->|否| H[检查pom.xml配置] G -->|是| I[验证MyBatis扫描路径] I --> J[检查@MapperScan] J --> K[完成] ``` ### 相关问题 1. MyBatis 中 `namespace` 和 `id` 的作用是什么? 2. 如何在 Spring Boot 中配置多模块的 MyBatis 映射文件路径? 3. Maven 资源过滤配置无效的可能原因有哪些? [^1]: 绑定异常通常由 XML 映射文件缺失或配置错误引起。 [^3]: 需在 `SqlSessionFactoryBean` 中明确指定 `mapperLocations`。 [^4]: Maven 需显式包含 `src/main/java` 下的 XML 文件。 [^5]: 资源目录配置是解决该问题的常见方案。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值