Spring+mybaits 配置遇到的问题
2021 年,八月,在学习 springboot+mybatis 的时候遇到了一些问题:
1、spring 启动谬误
刚开始,在配置 springboot+mybaits 的时候,依据网络上的博客,配置 application.yml,配置 UserMapper 等文件
application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/t_blog?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: 123456
mybatis:
type-aliases-package: com.mybatislearn.mockingjay.entity
mapper-locations: classpath:mapper/*.xml
server:
port: 8080
UserMapper.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.mybatislearn.mockingjay.mapper.UserMapper">
<resultMap id="UserMap" type="com.mybatislearn.mockingjay.entity.User" >
<id column="id" property="id" />
<result column="avatar" property="avatar" />
<result column="createTime" property="createTime" />
<result column="email" property="email" />
<result column="nickname" property="nickname" />
<result column="password" property="password" />
<result column="type" property="type" />
<result column="updateTime" property="updateTime" />
<result column="username" property="username" />
</resultMap>
<!-- 依据用户名查问用户 -->
<select id="loadUserByUsername" resultMap="UserMap">
select * from t_user where username=#{username}
</select>
</mapper>
配置一个 mapper 接口
UserMapper.java
package com.mybatislearn.mockingjay.mapper;
import com.mybatislearn.mockingjay.entity.User;
public interface UserMapper {User loadUserByUsername(String username);
}
同时我的项目内也是 MVC 构造的:
service
UserService.java
package com.mybatislearn.mockingjay.service;
import com.mybatislearn.mockingjay.entity.User;
public interface UserService {User queryUserByname(String name);
}
UserServiceImpl.java
package com.mybatislearn.mockingjay.service;
import com.mybatislearn.mockingjay.entity.User;
import com.mybatislearn.mockingjay.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
@Override
public User queryUserByname(String name) {User user = userMapper.loadUserByUsername(name);
return user;
}
}
Controller
package com.mybatislearn.mockingjay.controller;
import com.mybatislearn.mockingjay.entity.User;
import com.mybatislearn.mockingjay.mapper.UserMapper;
import com.mybatislearn.mockingjay.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/getuser")
public User GetUser(String name) {System.out.println(name);
User user = userService.queryUserByname(name);
return user;
}
}
最初是一个 User 实体
User.java
package com.mybatislearn.mockingjay.entity;
import lombok.Data;
import lombok.ToString;
import java.time.LocalDateTime;
@Data
@ToString
public class User {
private Long id;
private String avatar;
private LocalDateTime createTime;
private String email;
private String nickname;
private String password;
private Integer type;
private LocalDateTime updateTime;
private String username;
}
最初是 pom 文件,这里只取 maven 依赖
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.8</version>
</dependency>
</dependencies>
在配置实现后呈现了 springboot 启动失败的问题:
打印的日志
APPLICATION FAILED TO START
Description:
An attempt was made to call a method that does not exist. The attempt was made from the following location:
org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.createHandlerMethod(AbstractHandlerMethodMapping.java:341)
The following method did not exist:
'void org.springframework.web.method.HandlerMethod.<init>(java.lang.String, org.springframework.beans.factory.BeanFactory, org.springframework.context.MessageSource, java.lang.reflect.Method)'
The method's class, org.springframework.web.method.HandlerMethod, is available from the following locations:
```
jar:file:/C:/Users/xzh11/.m2/repository/org/springframework/spring-web/5.3.8/spring-web-5.3.8.jar!/org/springframework/web/method/HandlerMethod.class
```
The class hierarchy was loaded from the following locations:
```
org.springframework.web.method.HandlerMethod: file:/C:/Users/xzh11/.m2/repository/org/springframework/spring-web/5.3.8/spring-web-5.3.8.jar
```
Action:
Correct the classpath of your application so that it contains a single, compatible version of org.springframework.web.method.HandlerMethod
Process finished with exit code 0
在查阅材料后,我感觉是我应用的 spring 版本的问题,我的项目内我应用的是 2.5.4snapshot
<version>2.5.4-SNAPSHOT</version>
进入官网后,看到 springboot 最新的稳固版本为 2.5.3
springboot 官网
替换 springboot 版本为 2.5.3
<version>2.5.3</version>
胜利启动 springboot!
2、mybais 报错 Invalid bound statement
在启动 springboot 后,对 Controller 进行测试,后果呈现 mybatis 报错 Invalid bound statement
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.mybatislearn.mockingjay.mapper.UserMapper.loadUserByUsername
at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:53) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.binding.MapperProxy.lambda$cachedInvoker$0(MapperProxy.java:115) ~[mybatis-3.5.6.jar:3.5.6]
at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708) ~[na:na]
at org.apache.ibatis.binding.MapperProxy.cachedInvoker(MapperProxy.java:102) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:85) ~[mybatis-3.5.6.jar:3.5.6]
at com.sun.proxy.$Proxy57.loadUserByUsername(Unknown Source) ~[na:na]
at com.mybatislearn.mockingjay.service.UserServiceImpl.queryUserByname(UserServiceImpl.java:15) ~[classes/:na]
at com.mybatislearn.mockingjay.controller.UserController.GetUser(UserController.java:21) ~[classes/:na]
......
在折腾了一上午之后,发现还是配置的谬误:
在 UserMapper 文件中的 namespace 没有写对!!!!!
<?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.mybatislearn.mockingjay.mapper.UserMapper">
<resultMap id="UserMap" type="com.mybatislearn.mockingjay.entity.User" >
<id column="id" property="id" />
<result column="avatar" property="avatar" />
<result column="createTime" property="createTime" />
<result column="email" property="email" />
<result column="nickname" property="nickname" />
<result column="password" property="password" />
<result column="type" property="type" />
<result column="updateTime" property="updateTime" />
<result column="username" property="username" />
</resultMap>
<!-- 依据用户名查问用户 -->
<select id="loadUserByUsername" resultMap="UserMap">
select * from t_user where username=#{username}
</select>
</mapper>
3、总结
这次的谬误排查用了我将近一天的工夫,对于老手来说,太折磨了
于是,写一个文档进行记录,避免下次再遇到同样的问题。
springboot 启动失败的时候,若日志显示找不到什么文件,预计是配置的问题。
配置我的项目的时候最好再官网上查查稳固的版本。
在配置 mybatis 的时候,容易犯的谬误:
1、要留神属性文件中,实体类地址和 mapper 地址是否正确
type-aliases-package: com.mybatislearn.mockingjay.entity
mapper-locations: classpath:mapper/*.xml
2、配置 Mapper.xml 的时候,留神 <mapper> 标签下的 namespace 是否正确
<mapper namespace="com.mybatislearn.mockingjay.mapper.UserMapper">
留神 <resultMap> 标签中的 type 地址是否正确
<resultMap id="UserMap" type="com.mybatislearn.mockingjay.entity.User" >
映射语句中的 id 是否正确对应映射接口的办法名
<select id="loadUserByUsername" resultMap="UserMap">
select * from t_user where username=#{username}
</select>
package com.mybatislearn.mockingjay.mapper;
import com.mybatislearn.mockingjay.entity.User;
public interface UserMapper {User loadUserByUsername(String username);
}