Skip to content

🐦MyBatis


一、介绍


bc6827d5-7784-46c3-9f6a-bd551dce1ef9
  • 什么是 MyBatis ?

    • MyBatis 是一款优秀的 持久层框架 ,用于简化 JDBC 的开发。

    • MyBatis 本是 Apache 的一个开源项目 iBatis ,2010年这个项目由 apache

      迁移到了google code,并且改名为 MyBatis 。2013年11月迁移到 Github

  • 官网:https://mybatis.org/mybatis-3/zh_CN/index.html


在上面我们提到了两个词:一个是 持久层 ,另一个是 框架 。

  • 持久层:指的是就是数据访问层 (dao) ,是用来操作数据库的。
dfb60bcb-ddc2-48f0-978d-479a14c645fe
  • 框架 :是一个半成品软件,是一套可重用的、通用的、软件基础代码模型。

    在框架的基础上进行软件开发更加高效、规范、通用、可拓展。


通过 Mybatis 就可以大大简化原生的 JDBC 程序的代码编写,比如 通过 select * from user

查询所有的用户数据,通过 JDBC 程序操作呢,需要大量的代码实现,而如果通过 Mybatis 实现相同的功能,

只需要简单的三四行就可以搞定。

c4987734-0f0e-4799-9960-cc4f7206647e

二、快速入门


需求:使用 Mybatis 查询所有用户数据 。


  • 1). 创建 springboot 工程,并导入 mybatis 的起步依赖、mysql 的驱动包、lombok
891a6732-49fc-4731-b441-fbe83f42a948
0d045ad9-bd10-419b-99b1-9a1e218da3aa
  • 项目工程创建完成后,自动在 pom.xml 文件中,导入 Mybatis 依赖和 MySQL 驱动依赖。如下所示:
29b1169e-18f8-4f93-b884-a4f516ece045
  • 2). 数据准备:创建用户表 user ,并创建对应的实体类 User


    • 用户表 user(如果已经存在,就不用创建了)
    sql
    create table user(
        id int unsigned primary key auto_increment comment 'ID,主键',
        username varchar(20) comment '用户名',
        password varchar(32) comment '密码',
        name varchar(10) comment '姓名',
        age tinyint unsigned comment '年龄'
    ) comment '用户表';
    
    insert into user(id, username, password, name, age) 
    values  (1, 'daqiao', '123456', '大乔', 22),
    		(2, 'xiaoqiao', '123456', '小乔', 18),
    		(3, 'diaochan', '123456', '貂蝉', 24),
    		(4, 'lvbu', '123456', '吕布', 28),
    		(5, 'zhaoyun', '12345678', '赵云', 27);

    • 实体类:实体类的属性名与表中的字段名一一对应。 实体类放在 com.itheima.pojo 包下。
    java
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class User {
        private Integer id; //ID
        private String username; //用户名
        private String password; //密码
        private String name; //姓名
        private Integer age; //年龄
    }

  • 3). 配置 Mybatis : 在 application.properties 中配置数据库的连接信息。
properties
#数据库访问的url地址
spring.datasource.url=jdbc:mysql://localhost:3306/web
#数据库驱动类类名
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#访问数据库-用户名
spring.datasource.username=root
#访问数据库-密码
spring.datasource.password=1234

  • 4). 编写 Mybatis 程序:编写 Mybatis 的持久层接口,定义 SQL 语句(注解)

在创建出来的 springboot 工程中,在引导类所在包下,在创建一个包 mapper

mapper 包下创建一个接口 UserMapper ,这是一个持久层接口

Mybatis 的持久层接口规范一般都叫 XxxMapper)。

java
import com.itheima.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;

@Mapper
public interface UserMapper {
    /**
     * 查询全部
     */
    @Select("select * from user")
    public List<User> findAll();
}

  • 注解说明:

    • @Mapper 注解:表示是 mybatis 中的 Mapper 接口

    程序运行时,框架会自动生成接口的实现类对象(代理对象),并给交 SpringIOC 容器管理

    • @Select 注解:代表的就是 select 查询,用于书写 select 查询语句

  • 5). 单元测试

在创建出来的 SpringBoot 工程中,在 src 下的 test 目录下,已经自动帮我们创建好了测试类 ,

并且在测试类上已经添加了注解 @SpringBootTest,代表该测试类已经与 SpringBoot 整合。

该测试类在运行时,会自动通过引导类加载 Spring 的环境(IOC 容器)。我们要测试那个 bean对象,

就可以直接通过 @Autowired 注解直接将其注入进行,然后就可以测试了。


测试类代码如下:

java
@SpringBootTest
class SpringbootMybatisQuickstartApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testFindAll(){
        List<User> userList = userMapper.findAll();
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

运行结果:

c27ad474-a9a6-4e3b-b790-d239ba39b81c

注意:测试类所在包,需要与引导类所在包相同。


三、辅助配置


3.1 配置SQL提示


默认我们在 UserMapper 接口上加的 @Select 注解中编写 SQL 语句是没有提示的。

如果想让 idea 给我们提示对应的 SQL 语句,我们需要在 IDEA 中配置与 MySQL 数据库的链接。

需要做如下配置:

1e90c226-4753-482c-82c1-65e8452853bb

配置完成之后,发现 SQL 语句中的关键字有提示了,但还存在 不识别表名(列名) 的情况:

30a95749-1851-4dd7-a1e3-cb2ae7c895f7
  • 产生原因:Idea 和数据库没有建立连接,不识别表信息
  • 解决方案:在 Idea 中配置 MySQL 数据库连接

按照如下方如下方式,来配置当前 IDEA 关联的 MySQL 数据库(必须要指定连接的是哪个数据库)。

b118aaef-7e30-4120-92b3-c13f7cacc6f9
3a0e9e64-978d-4d8e-9e8f-806fac1e0475

在配置的时候指定连接那个数据库,如上图所示连接的就是 web01 数据库

自己的数据库名是什么就指定什么 -- 本质是在指定数据库下检测 SQL 语句的表)。


📌 注意 :

该配置的目的,仅仅是为了在编写 SQL 语句时,有语法提示(写错了会报错),

不会影响运行,即使不配置也是可以的。


3.2 配置Mybatis日志输出


默认情况下,在 Mybatis 中,SQL 语句执行时,我们并看不到 SQL 语句的执行日志。

application.properties 加入如下配置,即可查看日志:

properties
# mybatis的日志输出配置
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

打开上述开关之后,再次运行单元测试,就可以看到控制台输出的 SQL 语句是什么样子的。

766e5fbd-f5be-4e49-917c-6b63753077fc

四、JDBC VS Mybatis


JDBC 程序的

  • urlusernamepassword 等相关参数全部 硬编码java 代码中。

  • 查询结果的解析、封装比较繁琐。

  • 每一次操作数据库之前,先获取连接,操作完毕之后,关闭连接。

    频繁的获取连接、释放连接造成资源浪费。


分析了 JDBC 的缺点之后,我们再来看一下在 mybatis 中,是如何解决这些问题的:

  • 数据库连接四要素 (驱动、链接、用户名、密码),都配置

    springboot 默认的配置文件 application.properties

  • 查询结果的解析及封装,由 mybatis 自动完成映射封装,我们无需关注

  • mybatis 中使用了数据库连接池技术,从而避免了频繁的创建连接、销毁连接而带来的资源浪费。

5382d70c-59d7-4a27-a91c-f9ef64c47de9

📌 ​使用 SpringBoot + Mybatis 的方式操作数据库,能够提升开发效率、降低资源浪费


而对于 Mybatis 来说,我们在开发持久层程序操作数据库时,需要重点关注以下两个方面:

  • 1). application.properties
properties
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/web01
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=1234

  • 2). Mapper 接口(编写SQL语句)
java
@Mapper
public interface UserMapper {
    @Select("select * from user")
    public List<User> list();
}

五、数据库连接池


在前面我们所讲解的 mybatis 中,使用了数据库连接池技术,

避免频繁的创建连接、销毁连接而带来的资源浪费。


5.1 介绍


  • 1). 没有数据库连接池的情况
737e7782-4b99-40cc-8300-b025a1a7c583
  • 客户端执行 SQL 语句:
    • 要先创建一个新的连接对象
    • 然后执行 SQL 语句
    • SQL 语句执行后又需要关闭连接对象从而释放资源
  • 每次执行 SQL 时都需要创建连接、销毁链接,这种频繁的重复创建销毁的过程是比较耗费计算机的性能。

  • 2). 有数据库连接池的情况
9a9cdfa3-a935-4a5c-9e82-579cea6b8f42

数据库连接池是个容器,负责分配、管理数据库连接 (Connection)

  • 程序在启动时,会在数据库连接池(容器)中,创建一定数量的 Connection 对象

允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个

  • 客户端在执行 SQL 时,先从连接池中获取一个 Connection 对象,

    然后在执行 SQL 语句,SQL 语句执行完之后,释放 Connection 时

    就会把 Connection 对象归还给连接池(Connection 对象可以复用


释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏

  • 客户端获取到 Connection 对象了,但是 Connection 对象并没有去访问数据库(处于空闲),

    数据库连接池发现 Connection对象的空闲时间 > 连接池中预设的最大空闲时间

    此时数据库连接池就会自动释放掉这个连接对象


数据库连接池的好处:

  • 资源重用
  • 提升系统响应速度
  • 避免数据库连接遗漏

5.2 产品


要怎么样实现数据库连接池呢 ?

  • 官方 (sun) 提供了数据库连接池标准(javax.sql.DataSource 接口)

  • 功能:获取连接

java
public Connection getConnection() throws SQLException;
  • 第三方组织必须按照 DataSource 接口实现

常见的数据库连接池:C3P0DBCPDruidHikari (springboot默认)

现在使用更多的是:HikariDruid (性能更优越)


  • 1). Hikari(追光者) [默认的连接池]
8f9bec8e-632d-4f58-ae3a-352b7307c844

从控制台输出的日志,我们也可以看出,springboot 底层默认使用的数据库连接池就是 Hikari。


  • 2). Druid(德鲁伊)

  • Druid 连接池是阿里巴巴开源的数据库连接池项目

  • 功能强大,性能优秀,是 Java 语言最好的数据库连接池之一


如果我们想把默认的数据库连接池切换为Druid数据库连接池,只需要完成以下两步操作即可:

参考官方地址:https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter


  • ①. 在 pom.xml 文件中引入依赖
xml
<dependency>
    <!-- Druid连接池依赖 -->
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.19</version>
</dependency>

  • ②. 在 application.properties 中引入数据库连接配置
properties
# 指定数据库连接池的类型
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/web
spring.datasource.username=root
spring.datasource.password=1234

配置完毕之后,我们再次运行单元测试,大家会看到控制台输出的日志中,

已经将连接池切换为了 Druid 连接池 :

a87db902-d04f-4275-80c3-58c11346c7c3

六、增删改查操作


6.1 删除


  • 需求:根据 ID 删除用户信息
  • SQL:delete from user where id = 5

Mapper 接口方法:

  • 方式一:
java
/**
 * 根据id删除
 */
@Delete("delete from user where id = 5")
public void deleteById();

📌 这种方式执行删除操作,调用 deleteById 方法只能删除 id 为 5 的用户信息,

因为将 id 直接写死在代码中了,不可取。

  • 方式二:
java
/**
 * 根据id删除
 */
@Delete("delete from user where id = #{id}")
public void deleteById(Integer id);

Mybatis 中,我们可以通过参数占位符号 #{...} 来占位,

在调用deleteById方法时,传递的参数值,最终会替换占位符。


  • 编写单元测试方法进行测试

    在单元测试类中,增加如下测试方法.

java
@Test
public void testDeleteById(){
    userMapper.deleteById(36);
}

运行单元测试,结果如下:

e5ac67d0-0484-4c66-92df-78969ef3dbf4

📌 运行之后,我们发现,#{...} 占位符,其实最终被替换成了 占位符,

生成的是 预编译的SQL语句 。【推荐】


  • DML 语句执行完毕,是有返回值的,我们可以为 Mapper 接口方法定义返回值来接收,如下:
java
/**
 * 根据id删除
 */
@Delete("delete from user where id = #{id}")
public Integer deleteById(Integer id);

📌 Integer 类型的返回值,表示 DML 语句执行完毕影响的记录数。


  • Mybatis 的提供的符号,有两个,一个是 #{...},另一个是 ${...},区别如下:
符号说明场景
#{}占位符。执行时,会将 #{} 替换成 ? , 生成预编译SQL参数值传递
${}拼接符。直接将参数拼接在SQL语句中,存在SQL注入问题表名、字段名动态设置时使用

在企业项目开发中,强烈建议使用 #{...}


6.2 新增


  • 需求:添加一个用户
  • SQL:insert into user(username,password,name,age) values('zhouyu','123456','周瑜',20)
  • Mapper 接口:
java
/**
 * 添加用户
 */
@Insert("insert into user(username,password,name,age) values(#{username},#{password},#{name},#{age})")
public void insert(User user);

📌 注意:

如果在 SQL 语句中,我们需要传递多个参数,我们可以把多个参数封装到一个对象中。

然后在 SQL 语句中,我们可以通过 #{对象属性名} 的方式,获取到对象中封装的属性值。


  • 单元测试:

在测试类中添加测试方法,代码如下:

java
@Test
public void testInsert(){
    User user = new User();
    user.setUsername("admin");
    user.setPassword("123456");
    user.setName("管理员");
    user.setAge(30);
    userMapper.insert(user);
}

运行结果如下:

ffc94bcb-c992-4e97-8317-26d147ad91bc

6.3 修改


  • 需求:根据 ID 更新用户信息
  • SQL:update user set username = 'zhouyu', password = '123456', name = '周瑜', age = 20 where id = 1
  • Mapper 接口方法:
java
/**
 * 根据id更新用户信息
 */
@Update("update user set username = #{username},password = #{password},name = #{name},age = #{age} where id = #{id}")
public void update(User user);

  • 单元测试:

在测试类中添加测试方法,代码如下:

java
@Test
public void testUpdate(){
    User user = new User();
    user.setId(6);
    user.setUsername("admin666");
    user.setPassword("123456");
    user.setName("管理员");
    user.setAge(30);
    userMapper.update(user);
}

运行结果如下:

e1b90f69-6172-4644-8d63-f4d41a48f3d3

6.4 查询


  • 需求:根据 用户名和密码 查询用户信息
  • SQL:select* fromuser whereusername = 'zhouyu' and password = '123456'
  • Mapper 接口方法:
java
/**
 * 根据用户名和密码查询用户信息
 */
@Select("select * from user where username = #{username} and password = #{password}")
public User findByUsernameAndPassword(@Param("username") String username,@Param("password") String password);

📌 @Param 注解的作用是为接口的方法形参起名字的。

(由于用户名唯一的,所以查询返回的结果最多只有一个,可以直接封装到一个对象中)


❓ 为什么需要给形参起名字?

因为对接口传入的形参在编译成字节码文件的时候不会保留形参的名字

这样的话,mybatis 就不知道哪个值对应哪个值了


  • 单元测试:

在测试类中添加测试方法,代码如下:

java
@Test
public void testFindByUsernameAndPassword(){
    User user = userMapper.findByUsernameAndPassword("admin666", "123456");
    System.out.println(user);
}

运行结果如下:

d2d4d066-7198-48be-b2c4-2fc8cf764e88

📌 说明:

基于官方骨架创建的 springboot 项目中,接口编译时会保留方法形参名,

@Param 注解可以省略 (#{形参名})。


更进一步来说,我们可以观察基于官方骨架创建的 springboot 项目

编译所产生的字节码文件,相对比于基于阿里巴巴骨架创建的产生的字节码文件

官方骨架创建的会保留形参名字,这就是可以省略的原因所在

3f55477a-37cb-481c-8347-e17269003b10

七、XML映射配置


  • Mybatis 的开发有两种方式:
    • 注解
    • XML

7.1 XML配置文件规范


使用 Mybatis 的注解方式,主要是来完成一些 简单的增删改查 功能 。

如果需要实现 复杂的SQL 功能,建议使用 XML 来配置映射语句,

也就是将 SQL 语句写在 XML 配置文件中。


📌 在Mybatis中使用XML映射文件方式开发,需要符合一定的规范:

  1. XML 映射文件的名称Mapper 接口名称 一致,

    并且将 XML 映射文件和 Mapper 接口放置在相同包下(同包同名)

  2. XML 映射文件的 namespace 属性为 Mapper 接口全限定名 一致

  3. XML 映射文件中 sql 语句的 idMapper 接口中的方法名 一致,并保持返回类型一致。

abe06dc0-195d-4798-a376-20226fd5b338

<select> 标签:就是用于编写 select 查询语句的。

  • resultType 属性,指的是查询返回的单条记录所封装的类型。

7.2 XML配置文件实现


  • 第1步: 创建XML映射文件
00691777-d5a1-4566-8432-525a1bdea3cd
a39d7de6-6304-41f3-ba86-9d37c1f00acc
  • 第2步:编写XML映射文件

xml 映射文件中的 dtd 约束,直接从 mybatis 官网复制即可 ; 或者直接AI生成。

xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">
 
</mapper>

  • 第3步:配置

    • a. XML映射文件的 namespace 属性为Mapper接口全限定名
    xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.itheima.mapper.UserMapper"> 
    
    </mapper>
    • b. XML映射文件中 sql 语句的 id 与 Mapper 接口中的方法名一致,并保持返回类型一致
    xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.itheima.mapper.EmpMapper">
    
        <!--查询操作-->
        <select id="findAll" resultType="com.itheima.pojo.User">
            select * from user 
        </select>
        
    </mapper>

    • resultType 属性的值,与查询返回的单条记录封装的类型一致。

运行测试类,执行结果:

3a6cb4bd-822c-44ed-bc2f-07167a041ac9

📌 注意:一个接口方法对应的SQL语句,要么使用注解配置,

要么使用XML配置,切不可同时配置。


7.3 MybatisX的使用


  • MybatisX 是一款基于 IDEA 的快速开发 Mybatis 的插件,为效率而生

  • MybatisX 的安装:

4d55b711-5e63-4162-953d-db11bf5530d9
  • 可以通过 MybatisX 快速定位:
0bfe6139-3a69-47eb-b553-9e9685607ca6

MybatisX 的更多使用在会继续补充 ...


  • 学习了 Mybatis 中 XML 配置文件的开发方式了,可能会存在一个疑问:

    到底是使用注解方式开发还是使用 XML 方式开发?

官方说明:https://mybatis.net.cn/getting-started.html。

下面是官方说明:

fac36c6e-23f5-478c-8fb6-f3cd5cc7357f

📌 ​结论:使用 Mybatis 的注解,主要是来完成一些简单的增删改查功能。

如果需要实现复杂的 SQL 功能,建议使用 XML 来配置映射语句。


八、SpringBoot配置文件


8.1 介绍


前面我们一直使用 springboot 项目创建完毕后自带的 application.properties 进行属性的配置,

而如果在项目中,我们需要配置大量的属性,采用 properties 配置文件这种 key=value 的配置形式,

就会显得配置文件的层级结构不清晰,也比较臃肿。

c5c4f610-6ea4-4434-a5f2-549042ad5d05

那其实呢,在 springboot 项目当中是支持多种配置方式的,除了支持 properties 配置文件以外,

还支持另外一种类型的配置文件,就是接下来要讲解的 yml 格式的配置文件。

yml 格式配置文件名字为:application.yaml , application.yml

这两个配置文件的后缀名虽然不一样,但是里面配置的内容形式都是一模一样的。

我们可以来对比一下,采用 application.propertiesapplication.yml 来配置同一段信息

(数据库连接信息),两者之间的配置对比:

d7ebe2c8-71b1-4fa7-8ec0-66ada95b5759a6580be2-76cf-4ccc-be73-866ace6fe955

📌 在项目开发中,我们推荐使用 application.yml 配置文件来配置信息,简洁、明了、以数据为中心。


8.2 语法


简单的了解过 springboot 所支持的配置文件,以及不同类型配置文件之间的优缺点之后,

接下来我们就来了解下 yml 配置文件的基本语法:

  • 大小写敏感
  • 数值前边必须有空格,作为分隔符
  • 使用缩进表示层级关系,缩进时,不允许使用 Tab 键,只能用空格(idea 中会自动将 Tab 转换为空格)
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • # 表示注释,从这个字符一直到行尾,都会被解析器忽略
faa9f7e5-e8f9-41d6-ba8c-f106e7569c82
  • 了解完 yml 格式配置文件的基本语法之后,接下来我们再来看下 yml 文件中常见的数据格式。

    在这里我们主要介绍最为常见的两类:

    • 定义对象或 Map 集合
    • 定义数组、list 或 set 集合

  • 对象/Map集合
yaml
user:
  name: zhangsan
  age: 18
  password: 123456

  • 数组/List/Set集合
yaml
hobby: 
  - java
  - game
  - sport

❗ 在 yml 格式的配置文件中,如果配置项的值是以 0 开头的,

值需要使用 '' 引起来,因为以 0 开头在 yml中表示 8 进制的数据。


8.3 案例


熟悉完了 yml 文件的基本语法后,我们修改下之前案例中使用的配置文件,

变更为 application.yml 配置方式:

  • 修改 application.properties 名字为:_application.properties

    (名字随便更换,只要加载不到即可)

    或者说在配置好 yml 文件后直接删除掉都可以

  • 创建新的配置文件: application.yml


  • 原有的 application.properties 配置文件
0f05d99b-47ff-4e97-be36-848a44835dbd
  • 新建的 application.yml 配置文件
d72dd378-ee33-4405-9d8c-661aa41efba9

配置文件的内容如下:

yaml
#数据源配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/web01
    username: root
    password: 1234
#mybatis配置
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl