MyBatis-Plus 入门教程之一

大纲

前言

相关资源

版本说明

本文的教程内容是基于 MyBatis-Plus 3.5.2 版本编写的,若你使用的是 2.x 或其他版本,可能会有部分知识点、案例代码不兼容,一切以 MyBatis-Plus 官方文档为准。

MyBatis-Plus 介绍

MyBatis-Plus 是一款非常强大的 MyBatis 增强工具包,只做增强不做改变,为简化开发、提高效率而生。在不用编写任何 SQL 语句的情况下,可以极其方便地实现单一、批量、分页等操作。

MyBatis-Plus 特性

特色功能:

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内置分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 Delete 、Update 操作智能分析阻断,也可自定义拦截规则,预防误操作

支持数据库:

  • MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb
  • 达梦数据库,虚谷数据库,人大金仓数据库,南大通用 (华库) 数据库,南大通用数据库,神通数据库,瀚高数据库

MyBatis-Plus 架构

MyBatis-Plus 生态

  • MybatisX - 一款全免费且强大的 IDEA 插件,支持跳转、自动补全生成 SQL、代码生成。
  • Mybatis-Mate - MyBatis-Plus 的企业级模块,支持分库分表、数据审计、字段加密、数据绑定、数据权限、表结构自动生成 SQL 维护等高级特性。
  • Dynamic-Datasource - 基于 SpringBoot 的多数据源组件,功能强悍,支持 Seata 分布式事务。
  • Shaun - 基于 Pac4J-JWT 的 WEB 安全组件,快速集成。
  • Lock4j - 基于 SpringBoot 且同时支持 RedisTemplate、Redission、Zookeeper 的分布式锁组件。
  • Kaptcha - 基于 SpringBoot 和 Google Kaptcha 的简单验证码组件。

MyBatis-Plus 学习路线

Spring 快速启动案例

这里主要介绍 Spring 如何快速整合 MyBatis 与 MyBatis-Plus。本节所需的案例代码,可以直接从 GitHub 下载对应章节 mybatis-plus-lesson-01

软件版本说明

名称版本
Druid1.2.11
Spring5.3.2
Logback1.2.3
MyBatis-Plus3.5.2

初始化数据库

1
2
3
4
5
6
7
8
9
10
11
12
CREATE DATABASE `mybatis_plus_lesson` DEFAULT CHARACTER SET utf8mb4;

CREATE TABLE `t_employee` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`last_name` varchar(255) DEFAULT NULL,
`gender` char(1) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`age` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into t_employee(id, last_name, gender, email, age) values(1, 'Jim','1', 'jim@gmail.com', 26), (2, 'Peter','1', 'peter@gmail.com', 29);

引入 Maven 依赖

值得注意的是,这里不需要单独引入 MyBatis 与 MyBatis-Spring 的依赖,否则会引起版本冲突,这是因为 MyBatis-Plus 会自动维护它们的版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<properties>
<junit.version>4.12</junit.version>
<slf4j.version>1.7.30</slf4j.version>
<logback.version>1.2.3</logback.version>
<druid.version>1.2.11</druid.version>
<mybatis-plus.version>3.5.2</mybatis-plus.version>
<mysql-connector.version>8.0.23</mysql-connector.version>
<spring.version>5.3.2</spring.version>
</properties>

<dependencies>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>

<!-- Druid 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>

<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
</dependency>

<!-- MyBatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>

<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>

<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
</dependencies>

创建项目配置文件

数据库配置文件

/src/main/resources 目录下创建 db.properties 配置文件,其中的配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
jdbc.user=root
jdbc.password=123456
jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis_plus_lesson?characterEncoding=utf8&autoReconnect=true&useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC

jdbc.miniPoolSize=10
jdbc.maxPoolSize=30
jdbc.initialPoolSize=1
jdbc.maxWait=60000
jdbc.timeBetweenEvictionRunsMillis=60000
jdbc.minEvictableIdleTimeMillis=300000
jdbc.preferredTestQuery=select 1

Logback 配置文件

/src/main/resources 目录下创建 logback.xml 配置文件,其中的配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">

<!-- 定义日志文件的存储地址 -->
<property name="LOG_HOME" value="/tmp/mybatis-plus/logs" />

<!-- 控制台日志输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!-- 格式化输出:%d 表示日期,%thread 表示线程名,%-5level:表示级别从左显示5个字符宽度,%msg:表示日志消息,%n:表示换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>

<!-- MyBatis 日志打印 -->
<logger name="com.apache.ibatis" level="TRACE" />
<logger name="java.sql.Connection" level="DEBUG" />
<logger name="java.sql.Statement" level="DEBUG" />
<logger name="java.sql.PreparedStatement" level="DEBUG" />

<!-- 日志输出级别 -->
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>

</configuration>

MyBatis 配置文件

/src/main/resources 目录下创建 mybatis-config.xml 配置文件,用于存放 MyBatis 的全局核心配置信息,其中的配置内容如下:

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

</configuration>

Spring 配置文件

/src/main/resources 目录下创建 application.xml 配置文件,Spring 整合 MyBatis + MyBatis-Plus 的核心配置信息就写在里面(也就是定义 SqlSessionFactoryBean 的 Bean),其中的配置内容如下:

MyBatis-Plus 2.x 版本配置

提示

MyBatis-Plus 2.x 的 Spring 详细配置参数可看 这里

当使用的 MyBatis-Plus 为 2.x 版本时(如 2.3.3 版本),具体的配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

<!-- 引入数据库配置文件 -->
<context:property-placeholder location="classpath:db.properties" />

<!-- 数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="${jdbc.maxPoolSize}" />
<property name="initialSize" value="${jdbc.initialPoolSize}" />
<property name="maxWait" value="${jdbc.maxWait}" />
<property name="minIdle" value="${jdbc.miniPoolSize}" />
<property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}" />
<property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}" />
<property name="validationQuery" value="${jdbc.preferredTestQuery}" />
<property name="testWhileIdle" value="true" />
<property name="filters" value="stat" />
</bean>

<!-- 事务管理 -->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- 开启基于注解的事务 -->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager" />

<!-- 定义 SqlSessionFactory -->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 类型别名 -->
<property name="typeAliasesPackage" value="com.clay.mybatis.bean" />
<!--指定 SQL 映射文件的位置 -->
<property name="mapperLocations" value="classpath*:mapper/**/*.xml" />
<!-- 指定 MyBatis 全局配置文件的位置 -->
<property name="configLocation" value="classpath:mybatis-config.xml" />
<!-- 注入 Mybatis-Plus 的全局配置 -->
<property name="globalConfig" ref="globalConfig"></property>
</bean>

<!-- 定义 Mybatis-Plus 的全局配置 -->
<bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 数据库表字段名与 JavaBean 属性名的驼峰命名映射,在 2.3 版本以后,默认值是 true -->
<property name="dbColumnUnderline" value="true"></property>
<!-- 全局的主键策略 -->
<property name="idType" value="0"></property>
<!-- 全局的表前缀策略配置 -->
<property name="tablePrefix" value="t_"></property>
</bean>

<!-- 扫描 Mapper 接口 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.clay.mybatis.dao" />
</bean>

</beans>

提示

若不希望在项目中单独创建 MyBatis 的全局配置文件,可以使用 MybatisConfiguration 定义 MyBatis 的原生配置内容,这样就不再需要创建并指定 MyBatis 的全局配置文件了,配置示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<property name="configuration" ref="mybatisConfig"/>
<property name="globalConfig" ref="globalConfig"/>
...
</bean>

<bean id="mybatisConfig" class="com.baomidou.mybatisplus.MybatisConfiguration">
<!-- 开启自动驼峰命名规则映射 -->
<property name="mapUnderscoreToCamelCase" value="true"/>
...
</bean>

<bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
...
</bean>
MyBatis-Plus 3.x 版本配置

提示

MyBatis-Plus 3.x 的 Spring 详细配置参数可看 这里

当使用的 MyBatis-Plus 为 3.5 版本时(如 3.5.2 版本),具体的配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

<!-- 引入数据库配置文件 -->
<context:property-placeholder location="classpath:db.properties" />

<!-- 数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="${jdbc.maxPoolSize}" />
<property name="initialSize" value="${jdbc.initialPoolSize}" />
<property name="maxWait" value="${jdbc.maxWait}" />
<property name="minIdle" value="${jdbc.miniPoolSize}" />
<property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}" />
<property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}" />
<property name="validationQuery" value="${jdbc.preferredTestQuery}" />
<property name="testWhileIdle" value="true" />
<property name="filters" value="stat" />
</bean>

<!-- 事务管理 -->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- 开启基于注解的事务 -->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager" />

<!-- 定义 SqlSessionFactory -->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- 类型别名 -->
<property name="typeAliasesPackage" value="com.clay.mybatis.bean" />
<!--指定 SQL 映射文件的位置 -->
<property name="mapperLocations" value="classpath*:mapper/**/*.xml" />
<!-- 指定 MyBatis 全局配置文件的位置 -->
<property name="configLocation" value="classpath:mybatis-config.xml" />
<!-- 注入 Mybatis-Plus 的全局配置 -->
<property name="globalConfig" ref="globalConfig"></property>
</bean>

<!-- 定义 Mybatis-Plus 的全局配置 -->
<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
<property name="dbConfig" ref="dbConfig" />
</bean>

<!-- 定义 Mybatis-Plus 的数据库配置 -->
<bean id="dbConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig">
<!-- 全局的主键策略 -->
<property name="idType" value="AUTO"></property>
<!-- 全局的表前缀策略配置 -->
<property name="tablePrefix" value="t_"></property>
</bean>

<!-- 扫描 Mapper 接口 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.clay.mybatis.dao" />
</bean>

</beans>

提示

若不希望在项目中单独创建 MyBatis 的全局配置文件,可以使用 MybatisConfiguration 定义 MyBatis 的原生配置内容,这样就不再需要创建并指定 MyBatis 的全局配置文件了,配置示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="configuration" ref="configuration"/>
<property name="globalConfig" ref="globalConfig"/>
...
</bean>

<bean id="configuration" class="com.baomidou.mybatisplus.core.MybatisConfiguration">
<!-- 开启二级缓存 -->
<property name="cacheEnabled" value="true">
<!-- 开启自动驼峰命名规则映射 -->
<property name="mapUnderscoreToCamelCase" value="true">
...
</bean>

<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
<property name="dbConfig" ref="dbConfig"/>
...
</bean>

<bean id="dbConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig">
...
</bean>

通用 CRUD 代码

在项目开发中,使用 MyBatis 与 MyBatis-Plus 编写 CRUD 代码的区别:

  • 基于 Mybatis 的方式

    • 需要编写 Mapper 接口,并手动编写 CRUD 方法
    • 提供 SQL 映射文件,并手动编写每个 CRUD 方法对应的 SQL 语句
  • 基于 MyBatis-Plus 的方式

    • 简单的 CRUD 业务只需要创建 Mapper 接口,并继承 BaseMapper 接口,这就是使用 MyBatis-Plus 所需要的操作,甚至可以不创建 SQL 映射文件
JavaBean 类
1
2
3
4
5
6
7
8
9
10
11
public class Employee {

private Long id;
private String lastName;
private String gender;
private String email;
private Integer age;

...

}
Mapper 接口
1
2
3
4
5
public interface EmployeeMapper extends BaseMapper<Employee> {

public Employee getById(Long id);

}
SQL 映射文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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.clay.mybatis.dao.EmployeeMapper">

<select id="getById" parameterType="Long" resultType="Employee">
select id, last_name as lastName, gender, email, age
from t_employee
where id = #{id}
</select>

</mapper>
Junit 单元测试类
  • 方式一:通过 IOC 容器测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class IocContainerTest {

private static final ClassPathXmlApplicationContext iocContext = new ClassPathXmlApplicationContext("application.xml");

private static final EmployeeMapper empMapper = iocContext.getBean("employeeMapper", EmployeeMapper.class);

@Test
public void select() {
Employee employee = empMapper.selectById(1L);
Assert.notNull(employee, "entity not be null");
System.out.println(employee);
}

@Test
public void insert() {
Employee employee = new Employee("David", "1", "david@gmail.com", 23);
Integer insertResult = empMapper.insert(employee);
Assert.isTrue(insertResult > 0, "");
System.out.println("insert result: " + insertResult);
}

@Test
public void getById() {
Employee employee = empMapper.getById(1L);
Assert.notNull(employee, "entity not be null");
System.out.println(employee);
}

}
  • 方式二:通过 Spring + Junit 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:application.xml")
public class MyBatisPlusTest {

@Autowired
private EmployeeMapper empMapper;

@Test
public void select() {
Employee employee = empMapper.selectById(1L);
Assert.notNull(employee, "entity not be null");
System.out.println(employee);
}

@Test
public void insert() {
Employee employee = new Employee("David", "1", "david@gmail.com", 23);
Integer insertResult = empMapper.insert(employee);
Assert.isTrue(insertResult > 0, "");
System.out.println("insert result: " + insertResult);
}

@Test
public void getById() {
Employee employee = empMapper.getById(1L);
Assert.notNull(employee, "entity not be null");
System.out.println(employee);
}

}

执行上述的单元测试代码后,若控制台输出下面类似的日志信息,则说明 Spring 与 MyBatis-Plus 正常工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
2022-09-01 21:10:50.534 [main] DEBUG com.clay.mybatis.dao.EmployeeMapper.selectById - ==>  Preparing: SELECT id,last_name,gender,email,age FROM t_employee WHERE id=?
2022-09-01 21:10:50.535 [main] DEBUG com.clay.mybatis.dao.EmployeeMapper.selectById - ==> Parameters: 1(Long)
2022-09-01 21:10:50.557 [main] DEBUG com.clay.mybatis.dao.EmployeeMapper.selectById - <== Total: 1
Employee [id=1, lastName=David, gender=1, email=david@gmail.com, age=23]

2022-09-01 21:10:50.464 [main] DEBUG com.clay.mybatis.dao.EmployeeMapper.insert - ==> Preparing: INSERT INTO t_employee ( last_name, gender, email, age ) VALUES ( ?, ?, ?, ? )
2022-09-01 21:10:50.510 [main] DEBUG com.clay.mybatis.dao.EmployeeMapper.insert - ==> Parameters: David(String), 1(String), david@gmail.com(String), 23(Integer)
2022-09-01 21:10:50.514 [main] DEBUG com.clay.mybatis.dao.EmployeeMapper.insert - <== Updates: 1
insert result: 1

2022-09-01 21:10:50.562 [main] DEBUG com.clay.mybatis.dao.EmployeeMapper.getById - ==> Preparing: select id, last_name as lastName, gender, email, age from t_employee where id = ?
2022-09-01 21:10:50.563 [main] DEBUG com.clay.mybatis.dao.EmployeeMapper.getById - ==> Parameters: 1(Long)
2022-09-01 21:10:50.564 [main] DEBUG com.clay.mybatis.dao.EmployeeMapper.getById - <== Total: 1
Employee [id=1, lastName=David, gender=1, email=david@gmail.com, age=23]

SpringBoot 快速启动案例

这里主要介绍 SpringBoot 如何快速整合 MyBatis 与 MyBatis-Plus,本节所需的案例代码,可以直接从 GitHub 下载对应章节 mybatis-plus-lesson-02

软件版本说明

名称版本
Druid1.2.11
SpringBoot2.7.3
MyBatis-Plus3.5.2

初始化数据库

1
2
3
4
5
6
7
8
9
10
11
12
CREATE DATABASE `mybatis_plus_lesson` DEFAULT CHARACTER SET utf8mb4;

CREATE TABLE `t_employee` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`last_name` varchar(255) DEFAULT NULL,
`gender` char(1) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`age` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into t_employee(id, last_name, gender, email, age) values(1, 'Jim','1', 'jim@gmail.com', 26), (2, 'Peter','1', 'peter@gmail.com', 29);

引入 Maven 依赖

值得注意的是,这里不需要单独引入 MyBatis 与 MyBatis-Spring 的依赖,否则会引起版本冲突,这是因为 MyBatis-Plus 会自动维护它们的版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<properties>
<druid.version>1.2.11</druid.version>
<mybatis-plus.version>3.5.2</mybatis-plus.version>
</properties>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<relativePath />
</parent>

<dependencies>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>

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

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

<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

<!-- Druid 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>

<!-- MyBatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>

</dependencies>

SpringBoot 配置文件

提示

  • SpringBoot 2.0(内置 jdbc5 驱动),驱动类使用的是 driver-class-name: com.mysql.jdbc.Driver
  • SpringBoot 2.1 及以上(内置 jdbc8 驱动),驱动类使用的是 driver-class-name: com.mysql.cj.jdbc.Driver
  • MySQL 5.7 版本的 URL 为 jdbc:mysql://127.0.0.1:3306/mybatis_plus_lesson?characterEncoding=utf-8&useSSL=false
  • MySQL 8.0 版本的 URL 为 jdbc:mysql://127.0.0.1:3306/mybatis_plus?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false,若不指定 serverTimezone=GMT%2B8 会导致连接 MySQL 时抛出异常

MyBatis-Plus 2.x 版本配置

提示

  • MyBatis-Plus 2.x 的 SpringBoot 详细配置参数可看 这里

当使用的 MyBatis-Plus 为 2.x 版本时(如 2.3.3 版本),具体的配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
spring:
# Druid 数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/mybatis_plus_lesson?characterEncoding=utf8&autoReconnect=true&useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: 123456
initial-size: 10
max-active: 100
min-idle: 10
max-wait: 60000
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1
test-while-idle: true
test-on-borrow: false
test-on-return: false
stat-view-servlet:
enabled: false
url-pattern: /druid/*
login-username: admin
login-password: 123456
filter:
stat:
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: false
wall:
config:
multi-statement-allow: true

# MyBatis-Plus 配置
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
type-aliases-package: com.clay.mybatis.bean
# MyBatis-Plus 全局配置
global-config:
id-type: 0
field-strategy: 2
db-column-underline: true
table-prefix: t_
# MyBatis 原生配置
configuration:
jdbc-type-for-null: 'null'
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

logging:
level:
com.clay.mybatis.dao: debug

若项目中有全局的 MyBatis 配置文件(XML),可以将其路径配置到 MyBatis-Plus 的 confifigLocation 中,如下所示:

1
2
3
mybatis-plus:
config-location: classpath:mybatis-config.xml
...

MyBatis-Plus 3.x 版本配置

提示

MyBatis-Plus 3.x 的 SpringBoot 详细配置参数可看 这里

当使用的 MyBatis-Plus 为 3.5 版本时(如 3.5.2 版本),具体的配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
spring:
# Druid 数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/mybatis_plus_lesson?characterEncoding=utf8&autoReconnect=true&useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: 123456
initial-size: 10
max-active: 100
min-idle: 10
max-wait: 60000
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1
test-while-idle: true
test-on-borrow: false
test-on-return: false
stat-view-servlet:
enabled: false
url-pattern: /druid/*
login-username: admin
login-password: 123456
filter:
stat:
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: false
wall:
config:
multi-statement-allow: true

# MyBatis-Plus 配置
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
type-aliases-package: com.clay.mybatis.bean
# MyBatis-Plus 全局配置
global-config:
banner: false
db-config:
id-type: AUTO
table-prefix: t_
table-underline: true
# MyBatis 原生配置
configuration:
jdbc-type-for-null: 'null'
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

logging:
level:
com.clay.mybatis.dao: debug

若项目中有全局的 MyBatis 配置文件(XML),可以将其路径配置到 MyBatis-Plus 的 confifigLocation 中,如下所示:

1
2
3
mybatis-plus:
config-location: classpath:mybatis-config.xml
...

通用 CRUD 代码

在项目开发中,使用 MyBatis 与 MyBatis-Plus 编写 CRUD 代码的区别:

  • 基于 Mybatis 的方式

    • 需要编写 Mapper 接口,并手动编写 CRUD 方法
    • 提供 SQL 映射文件,并手动编写每个 CRUD 方法对应的 SQL 语句
  • 基于 MyBatis-Plus 的方式

    • 简单的 CRUD 业务只需要创建 Mapper 接口,并继承 BaseMapper 接口,这就是使用 MyBatis-Plus 所需要的操作,甚至可以不创建 SQL 映射文件

JavaBean 类

1
2
3
4
5
6
7
8
9
10
11
public class Employee {

private Long id;
private String lastName;
private String gender;
private String email;
private Integer age;

...

}

Mapper 接口

1
2
3
4
5
public interface EmployeeMapper extends BaseMapper<Employee> {

public Employee getById(Long id);

}

SQL 映射文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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.clay.mybatis.dao.EmployeeMapper">

<select id="getById" parameterType="Long" resultType="Employee">
select id, last_name as lastName, gender, email, age
from t_employee
where id = #{id}
</select>

</mapper>

SpringBoot 启动类

通过 @MapperScan 注解来扫描 Mapper 接口。

1
2
3
4
5
6
7
8
9
@SpringBootApplication
@MapperScan("com.clay.mybatis.dao")
public class MyBatisPlusApplication {

public static void main(String[] args) {
SpringApplication.run(MyBatisPlusApplication.class, args);
}

}

Junit 单元测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@SpringBootTest
public class MyBatisPlusApplicationTest {

@Autowired
private EmployeeMapper empMapper;

@Test
public void select() {
Employee employee = empMapper.selectById(1L);
Assert.notNull(employee, "entity not be null");
System.out.println(employee);
}

@Test
public void insert() {
Employee employee = new Employee("David", "1", "david@gmail.com", 23);
Integer insertResult = empMapper.insert(employee);
Assert.isTrue(insertResult > 0, "");
System.out.println("insert result: " + insertResult);
}

@Test
public void getById() {
Employee employee = empMapper.getById(1L);
Assert.notNull(employee, "entity not be null");
System.out.println(employee);
}

}

执行上述的单元测试代码后,若控制台输出下面类似的日志信息,则说明 SpringBoot 与 MyBatis-Plus 正常工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
==>  Preparing: INSERT INTO t_employee ( last_name, gender, email, age ) VALUES ( ?, ?, ?, ? )
==> Parameters: David(String), 1(String), david@gmail.com(String), 23(Integer)
<== Updates: 1
insert result: 1

==> Preparing: SELECT id,last_name,gender,email,age FROM t_employee WHERE id=?
==> Parameters: 1(Long)
<== Columns: id, last_name, gender, email, age
<== Row: 1, Jim, 1, jim@gmail.com, 26
<== Total: 1
Employee [id=1, lastName=Jim, gender=1, email=jim@gmail.com, age=26]

==> Preparing: select id, last_name as lastName, gender, email, age from t_employee where id = ?
==> Parameters: 1(Long)
<== Columns: id, lastName, gender, email, age
<== Row: 1, Jim, 1, jim@gmail.com, 26
<== Total: 1
Employee [id=1, lastName=Jim, gender=1, email=jim@gmail.com, age=26]