自由不是你想做什么就能做什么,而是你不想做什么就可以不做什么。
目录
- 前言
- 数据库部分
- 整合部分
- 一波三折
- 数据库驱动
- 再次配置映射文件
- 再配数据源
- 回溯章节
前言
关于如何搭建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",这下终于完美了: