前言
使用springboot整合mybatis报如下错误。
Invalid bound statement (not found) :com.mc.mapper.UsersMapper.insertMapper
望闻问切
查看错误日志,只有一句无效绑定语句。推断是UsersMapper
未被扫描到。
分析出现该情况的原因大致有以下几种情况:
-
Mapper.xml中namespace与Mapper.java不一致。
检查一致。排除。
-
Mapper.xml中insert id与Mapper.java中Method名不一致。
检查一致。排除。
-
Mapper.xml中参数类型及返回值类型与Mapper.java中Method参数表不一致。
检查一致。排除。
-
UsersMapper
未注解为Mapper。尝试两种方式,1.启动器扫描。2.Mapper注解。 操作如下:
- 在
App.java
中添加注解@MapperScan("com.mc.mapper")
扫描。 - 在
UsersMapper.java
中添加注解@Mapper
两种方式均不能解决问题。
- 在
-
删除Mapper.xml中多余的空行并保存。
网上查到有这种方式解决问题的,想到此前jsp中也经常因为空格空行报错,尝试了一下。查看我的xml文件也有一些空行,删除后无效果。
对症下药
至此网上能查到的方式基本全部尝试无效了。翻阅手边书本(《Spring Boot+Vue全栈开发实战》王松 著 清华大学出版社)查看基本配置发现这样一段话:
在Maven工程中,XML配置文件建议写在resources目录下,但是上文中的Mapper.xml文件写在包下,Maven在运行时会忽略包下的XML文件,因此需要在pom.xml文件中重新指明资源文件位置,配置如下:
<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include> **/*.xml </include> </includes> </resource> </resources> </build>
看到里发现这个描述好像和我的工程目录一致,尝试添加该配置,重启项目,结果竟然无效!对症下药都无效,要哭辽。(╥╯^╰╥)
回头准备关闭项目继续问度娘时,突然看到IDEA出现一个M型图标,才想起来新版本IDEA修改完pom.xml文件后不再弹窗提示update了,而是在右上角显示一个Maven图标。reimport后重启,问题解决。依赖IDE害死人呀!!!!o(╥﹏╥)o
总结
在网上查看的挺多springboot整合mybatis资料或视频,均未做resources的多余操作仍能正常使用,猜测Maven可能是版本原因?出现该问题后排查思路总结如下:
- 查看基础配置是否完整,注解、文件名、方法名等。
- 查看是否IDE问题导致,将XML、JSP等兼容性不是很好的文件删除重建。
- 查看resources是否需要重新制定。
- 修改pom.xml后一定要reimport。
附录
以下为demo
pom.xml
<!- GAV坐标省略 ->
<dependencies>
<!--springboot启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
<!--web启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<!--mybatis启动器-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!--mysql 驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
<!--数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.23</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>
**/*.xml
</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
srcmain esourcesapplication.properties
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://*.*.*.*:port/ssm
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 包名前缀
mybatis.type-aliases-package=com.mc.pojo
com.mc.pojo.User
public class User {
private Integer id;
private String name;
private Integer age;
// get set
}
com.mc.mapper.UsersMapper
public interface UsersMapper {
void insertUser(User user);
}
commcmapperUsersMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mc.mapper.UsersMapper">
<insert id="insertUser" parameterType="user">
insert into t_user(name,age) values(#{name},#{age});
</insert>
</mapper>
com.mc.service.UserService
public interface UserService {
void addUser(User user);
}
com.mc.service.impl.UserServiceImpl
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UsersMapper usersMapper;
@Override
public void addUser(User user) {
System.out.println(user);
System.out.println(this.usersMapper);
this.usersMapper.insertUser(user);
}
}
com/mc/controller/UsersCtrl.java
@Controller
@RequestMapping("/users")
public class UsersCtrl {
@Autowired
private UserService userService;
@RequestMapping("/{page}")
public String showPage(@PathVariable String page){
return page;
}
@RequestMapping("/addUser")
public String addUser(User user){
System.out.println(user.toString());
this.userService.addUser(user);
return "ok";
}
}
com/mc/Application.java
@SpringBootApplication
@MapperScan("com.mc.mapper") // @MapperScan 用于扫描mybatis的mapper接口
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
表现层使用的thymeleaf做简单显示。
srcmain esources emplatesinput.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>添加用户</title>
</head>
<body>
<form th:action="@{/users/addUser}" method="post">
姓名:<input type="text" name="name" value="Admin">
年龄:<input type="text" name="age" value="10">
<input type="submit" value="确定">
</form>
</body>
</html>
srcmain esources emplatesok.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>操作提示页面</title>
</head>
<body>
操作成功~~~
</body>
</html>
访问录入页面测试即可 http://localhost:8080/users/input