史上踩坑最多的SpringBoot整合Mybatis

news/2024/10/30 23:14:03/
自由不是你想做什么就能做什么,而是你不想做什么就可以不做什么。

目录

  • 前言
  • 数据库部分
  • 整合部分
  • 一波三折
    • 数据库驱动
    • 再次配置映射文件
    • 再配数据源
    • 回溯章节

前言

关于如何搭建SpringBoot工程以及开启Web功能,
可以查看我的这篇博客:用Spring Initializr快速构建SpringBoot及整合MVC

数据库部分

本文使用的数据库为MySQL数据库,需要读者提前安装好

首先,在数据库"mydb"中创建一个"users"表,建表语句如下:

create table users # 创建表users
(					# 整型  不为空  自动增长id 				int not null auto_increment, username		varchar(50), # 可变字符串,最长为50password		varchar(50), # 可变字符串,最长为50primary key (id) # 设置id为主键
)

表结构:
在这里插入图片描述
再往表"users"中插入一条数据:

insert into users(username, password) values('古阙月', '123456');

此时,"users"表中为:
在这里插入图片描述

整合部分

1.首先,可以参照我的这篇博客搭建一个SpringBoot工程 -> 点击进入,除去之前在依赖管理文件pom.xml中配置的Web功能的起步依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

再在依赖管理文件pom.xml中分别引入Mybatis的起步依赖mybatis-spring-boot-starter、MySQL数据库的连接器依赖mysql-connector-java,如:

<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.1</version>
</dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope> <!-- 作用域:表示运行时才生效-->
</dependency>

需要注意的是,如果添加了Mybatis的起步依赖mybatis-spring-boot-starter一定要配置数据源。若是没有配置datasource数据源,就启动SpringBoot工程的话将会启动失败,并报错Failed to configure a DataSource(配置数据源失败)
在这里插入图片描述
2.配置数据源
找到配置文件application.yml,配置数据源,连接"mydb"数据库,如:

# 配置数据源
spring:datasource:url: jdbc:mysql:///mydb # 数据库路径 jdbc:mysql://localhost:3306/mydb 的缩写username: root          # 用户名password: 123456        # 密码driver-class-name: com.mysql.jdbc.Driver # 数据库驱动

再创建实体类,如:

/*** @author guqueyue* @Date 2020/4/12**/
//lombok插件的注解
@Data // 若未使用lombok插件,请自行生成getter、setter以及toString方法
@AllArgsConstructor // 若未使用lombok插件,请自行生成有参构造方法
@NoArgsConstructor // 若未使用lombok插件,请自行生成无参构造方法
@Accessors(chain = true) // 开启链式编程
public class User implements Serializable {private Integer id;private String username;private String password;
}

3.创建映射接口UserMapper和配置映射文件UserMapper.xml,如:

package com.guqueyue.dao;/*** @author guqueyue* @Date 2020/4/12* 映射接口UserMapper**/
public interface UserMapper {/*** 查询用户列表* @return*/List<User> userList();
}

在src/main/java/com/guqueyue/dao目录下配置映射文件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.guqueyue.dao.UserMapper"><!-- 查询用户列表 --><select id="userList" resultType="com.guqueyue.entity.User">select * from users</select></mapper>

MyBatis映射文件模板可以去我的这篇博客中查看如何配置:SpringBoot的常用代码模板,找到File and Code Templates中的MyBatis章节即可。

4.创建Service层,首先创建一个Service接口,如:

package com.guqueyue.service;public interface IUserService {/*** 查询用户列表* @return*/List<User> userList();
}

再创建service层实现类UserServiceImpl,实现接口IUserService中的方法,并在UserServiceImpl 实现类中注入UserMapper,如:

package com.guqueyue.service.impl;/*** @author guqueyue* @Date 2020/4/12**/
@Service
public class UserServiceImpl implements IUserService {@Autowired // 注入UserMapper相当于new对象private UserMapper userMapper;/*** 查询用户列表* @return*/public List<User> userList() {return userMapper.userList();}
}

5.创建Controller层,在UserController中注入serviec层接口IUserService ,写一个获取用户列表的方法,如:

package com.guqueyue.controller;/*** @author guqueyue* @Date 2020/4/12**/
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate IUserService userService;/*** 查询用户列表* @return*/@RequestMapping("/list")public List<User> userList() {return userService.userList();}
}

此处需要注意的是:如果没有配置映射文件UserMapper.xml以及映射接口的扫描,直接启动应用程序,将会启动失败,并报UserMapper没有找到故而注入失败,控制台报错信息如下:

***************************
APPLICATION FAILED TO START
***************************Description:Field userMapper in com.guqueyue.service.UserService required a bean of type 'com.guqueyue.dao.UserMapper' that could not be found.The injection point has the following annotations:- @org.springframework.beans.factory.annotation.Autowired(required=true)Action:Consider defining a bean of type 'com.guqueyue.dao.UserMapper' in your configuration.

反之,若是报相应错误,很可能是映射文件UserMapper.xml或者映射接口的扫描的配置出错!

6.在配置文件application.yml中,配置映射文件的扫描,如:

mybatis:# 配置映射文件的扫描mapper-locations: classpath:com/guqueyue/dao/*.xml# 配置别名的扫描type-aliases-package: com.guqueyue.entity

7.配置映射接口的扫描,在启动类上加上@MapperScan注解,如:

@SpringBootApplication(scanBasePackages = "com.guqueyue")
@MapperScan("com.guqueyue.dao") // 扫描映射接口
public class HelloGuqueyueApplication {public static void main(String[] args) {SpringApplication.run(HelloGuqueyueApplication.class, args);}
}

好像已经配置完成了,那就启动吧!

一波三折

数据库驱动

到这里,成功启动应用程序,控制台截图如下:
在这里插入图片描述
等等,这行红色的字是什么意思?

Loading class com.mysql.jdbc.Driver. This is deprecated. The new driver class is com.mysql.cj.jdbc.Driver. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

原来是之前配置的数据库驱动不推荐使用了,强迫症表示难受了,果断改驱动(当然,不改也不影响使用),更改后application.yml配置中数据源配置如下:

# 配置数据源
spring:datasource:                                 url: jdbc:mysql:///mydb # 数据库路径 jdbc:mysql://localhost:3306/mydb 的缩写username: root          # 用户名password: 123456        # 密码driver-class-name: com.mysql.cj.jdbc.Driver # 更改后的数据库驱动

再次启动,果然控制台不报了,舒服:
在这里插入图片描述

再次配置映射文件

接下来离成功就已经很近了,打开浏览器,让我们来输入"http://localhost:8080/user/list",来见证奇迹吧:
在这里插入图片描述
what?500??什么鬼?再到控制台一看,报错如下:

org.apache.ibatis.binding.BindingException:
Invalid bound statement (not found):com.guqueyue.dao.UserMapper.userList

找不到UserMapper中的userList方法,纳尼?你找不到你是怎么知道有这个方法的???那就很可能是映射文件UserMapper.xml出了问题,打开编译的target一看,果然映射文件UserMapper.xml没有被编译进去:
在这里插入图片描述
而我们工程目录是这样的:
在这里插入图片描述
突然想起SpringBoot的约定>配置,SpringBoot的配置文件一般要放到src/main/resources目录下,可是我却放到了src/main/java目录下。相当于我违反了与SprngBoot的约定,需要再次去pom.xml文件中的<build></build>中进行配置,以便SpringBoot扫到映射文件UserMapper.xml

<resources><!-- 使SpringBoot扫到映射文件 --><resource><directory>src/main/java</directory><includes><include>com/guqueyue/dao/*.xml</include></includes></resource><!-- 防止配置之后出现不扫resources的bug --><resource><directory>src/main/resources</directory></resource>
</resources>

再次运行应用程序,到target一看,这次映射文件UserMapper.xml果然编译进去了:
在这里插入图片描述

再配数据源

这样总该成功了吧,再次打开浏览器,输入"http://localhost:8080/user/list":
在这里插入图片描述
what?还是不行,到控制台一看, 又报错了:

com.mysql.cj.exceptions.InvalidConnectionAttributeException:
The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. 
You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specifc time zone value 
if you want to utilize time zone support.

"The server time zone"不是服务器的时区吗?这个有什么问题呢?
我们点开MySQL数据库的连接器依赖mysql-connector-java
在这里插入图片描述
发现是8点几的版本,不是我之前常用的5点几版本,那试着改一下版本吧:

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope> <!-- 作用域:表示运行时才生效--><version>5.1.47</version>
</dependency>

发现控制台还是报错,错误信息如下:

Caused by: java.lang.IllegalStateException: 
Cannot load driver class: com.mysql.cj.jdbc.Driver

那我们就再把数据库驱动换回来:

# 配置数据源
spring:datasource:                                 url: jdbc:mysql:///mydb # 数据库路径 jdbc:mysql://localhost:3306/mydb 的缩写username: root          # 用户名password: 123456        # 密码driver-class-name: com.mysql.jdbc.Driver # 数据库驱动

启动程序,打开浏览器输入"http://localhost:8080/user/list",浏览器显示:
在这里插入图片描述
简直完美!

回溯章节

等等你敢说完美?我就想用8点几版本的MySQL数据库连接器依赖怎么办呢?
让我们回到本章《再配数据源》最开始的地方,
MySQL数据库连接器依赖如下:

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope> <!-- 作用域:表示运行时才生效-->
</dependency>

数据源配置如下:

# 配置数据源
spring:datasource:url: jdbc:mysql:///mydb # 数据库路径 jdbc:mysql://localhost:3306/mydb 的缩写username: root          # 用户名password: 123456        # 密码driver-class-name: com.mysql.cj.jdbc.Driver # 更改后的数据库驱动

控制台报错信息:

com.mysql.cj.exceptions.InvalidConnectionAttributeException:
The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone. 
You must configure either the server or JDBC driver (via the 'serverTimezone' configuration property) to use a more specifc time zone value 
if you want to utilize time zone support.

既然mysql的服务器无法识别时区,那我们就配置一个时区!在数据源中配置一下时区,如我在的时区为东八区(GMT+8):

# 配置数据源
spring:datasource:# 数据库路径jdbc:mysql://localhost:3306/mydb 的缩写,并配置时区url: jdbc:mysql:///mydb?serverTimezone=GMT+8username: root          # 用户名password: 123456        # 密码driver-class-name: com.mysql.cj.jdbc.Driver # 更改后的数据库驱动

启动程序,控制台没报错,可是输入"http://localhost:8080/user/list",控制台又报错了,不过不是报之前serverTimezone的错误了,说明配置时区的思路还是对的,但是却报了一个sql异常:

java.sql.SQLException: No timezone mapping entry for 'GMT 8'

what? ‘GMT 8’,我不是配置的’GMT+8’吗?去配置文件一看:
在这里插入图片描述
没错呀,等等,这是个url,那它在连接数据库的时候,是不是会照我的数据库的字符编码utf-8进行解码(转义)呢?来模拟一下:

/*** @author guqueyue* @Date 2020/4/6**/
public class Test {public static void main(String[] args) throws Exception {String url = "jdbc:mysql:///mydb?serverTimezone=GMT+8";String newUrl = URLDecoder.decode(url, "utf-8");System.out.println(newUrl);}
}

运行main方法,控制台打印如下:
在这里插入图片描述
果然,"+“被转义了,既然”+“有问题,那我们就把”+"先用"utf-8"编码格式先编码试试:

/*** @author guqueyue* @Date 2020/4/6**/
public class Test {public static void main(String[] args) throws Exception {String str = "+";String s = URLEncoder.encode(str, "utf-8");System.out.println(s);}
}

控制台结果为:
在这里插入图片描述
既然如此,那我们就用"%2B“来代替”+",先建个demo测试一下:

/*** @author guqueyue* @Date 2020/4/6**/
public class Test {public static void main(String[] args) throws Exception {String url = "jdbc:mysql:///mydb?serverTimezone=GMT%2B8";String newUrl = URLDecoder.decode(url, "utf-8");System.out.println(newUrl);}
}

运行main方法,控制台打印:
在这里插入图片描述
这下完美了,不过不要高兴的太早了,更改application.yml配置文件中的数据源配置,如:

# 配置数据源
spring:datasource:# 数据库路径jdbc:mysql://localhost:3306/mydb 的缩写,并配置时区url: jdbc:mysql:///mydb?serverTimezone=GMT%2B8username: root          # 用户名password: 123456        # 密码driver-class-name: com.mysql.cj.jdbc.Driver # 更改后的数据库驱动

又或者,经过博主pxxobj的评论提醒,直接把时区换成上海时区也是可以的:

# 配置数据源
spring:datasource:# 数据库路径jdbc:mysql://localhost:3306/mydb 的缩写,并配置时区url: jdbc:mysql:///mydb?serverTimezone=Asia/Shanghaiusername: root          # 用户名password: 123456        # 密码driver-class-name: com.mysql.cj.jdbc.Driver # 更改后的数据库驱动

启动应用程序,打开浏览器,输入"http://localhost:8080/user/list",这下终于完美了:
在这里插入图片描述


http://www.ppmy.cn/news/463972.html

相关文章

跟父母还是要保持一定的距离感

背景 不知你有没有亲身经历过&#xff0c;或者见过身边的人正在经历下面这些场景&#xff1a; 自己交了男/女朋友&#xff0c;父母感觉不太好时劝分手结婚前&#xff0c;父母对另一半的询问或考验让对方难堪结婚后&#xff0c;父母经常帮忙处理家庭事务&#xff08;打扫卫生&a…

死磕Spring系列:Bean实例化原理

本文将从源码的角度来分析SpringBean的创建过程 1. BeanDefinition 大家都知道&#xff0c;在Spring IOC启动时&#xff0c;会扫描类的信息&#xff0c;将相关信息封装为BeanDefinition存入到beanDefinitionMap中&#xff0c;后续用其中的描述信息来生成bean。 2. getBean 首…

不分手,好吗?

你提出分手&#xff0c;显得那么平静&#xff0c;不带一丝惋惜。  当你来到我的身旁&#xff0c;我发现&#xff0c;平静的你是如此的美丽&#xff01;真的想抱住你&#xff0c;吻你……但我不能&#xff01;  你知道吗&#xff0c;你的这份美丽让我凭添了许多痛苦&#xf…

这个, ..., 男方也太背了吧, 尽碰上极品女方...

发信人: jungleford (風淸揚╬孤城斩菜羊), 信区: Joke 标 题: 我生活在上海&#xff0c;我相亲无数次&#xff0c;那些极品女方父母 (转载) 发信站: 水木社区 (Sun Aug 22 20:58:53 2010), 站内 【 以下文字转载自 Shanghai 讨论区 】 发信人: adi (杨过), 信区: Shanghai 标…

spring的beanfactory与applicationContext的区别以及继承关系

applicationContext继承关系 首先可以看一张图 ListableBeanFactory 可列举的bean工厂 hierarchical 分层bean工厂 messageSource 国际化信息 //国际化&#xff08;internationalization&#xff09;是设计和…

从分手厨房看拓扑排序

点击上方 "程序员小乐"关注, 星标或置顶一起成长 每天凌晨00点00分, 第一时间与你相约 每日英文 Dont judge people by their outlook for you dont know what stories behind their eyes. 不要以貌取人&#xff0c;因为你不知道他们的双眼后面藏着什么故事。 每日掏…

分手厨房2联机得买两份吗_你在厨房里表现出色吗?

分手厨房2联机得买两份吗 These days, I dont have to cook too often, but company is coming tonight. So, I dug out a slow cooker recipe, and got ready to brown the meat. 这些天&#xff0c;我不必经常做饭&#xff0c;但是公司今晚就要来了。 因此&#xff0c;我挖出…

掌握Spring Cloud:打造高效可靠的微服务生态系统

1、SpringCloud概述 Spring Cloud是一个用于构建分布式系统的开源框架&#xff0c;它提供了一系列的组件和工具&#xff0c;用于实现微服务架构中的各项核心功能。本文将重点介绍Spring Cloud中的关键组件&#xff0c;并详细探讨它们的功能和作用。 网关&#xff1a;Zuul/Gat…