史上踩坑最多的SpringBoot整合Mybatis

自由不是你想做什么就能做什么,而是你不想做什么就可以不做什么。

前言

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

数据库部分

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

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

create table users # 创建表users
(					# 整型  不为空  自动增长
	id 				int not null auto_increment, 
	username		varchar(50), # 可变字符串,最长为50
	password		varchar(50), # 可变字符串,最长为50
	primary 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 {

    @Autowired
    private 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+8
    username: 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%2B8
    username: 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/Shanghai
    username: root          # 用户名
    password: 123456        # 密码
    driver-class-name: com.mysql.cj.jdbc.Driver # 更改后的数据库驱动

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

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值