第 1 章 MybatisPlus 快速入门

第 1 章 MybatisPlus 快速入门

1、MybatisPlus 概述

MybatisPlus:一款 Mybatis 的增强工具包

MybatisPlus 官网:https://mybatis.plus/ 或 https://mp.baomidou.com/

第 1 章 MybatisPlus 快速入门_第1张图片

MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

愿景:我们的愿景是成为 MyBatis 最好的搭档,就像魂斗罗中的 1P、2P,基友搭配,效率翻倍。

MybatisPlus 的特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

MybatisPlus 文档地址

  1. 官方地址:http://mp.baomidou.com 或者 https://mybatis.plus/
  2. 代码发布地址:
    1. Github:https://github.com/baomidou/mybatis-plus
    2. Gitee:https://gitee.com/baomidou/mybatis-plus
  3. 文档发布地址:https://mp.baomidou.com/guide/

2、MybatisPlus 快速入门

2.1、环境搭建

0、参考资料

MybatisPlus 快速开始

1、创建数据库表

现有一张 User 表,其表结构如下

id name age email
1 Jone 18 [email protected]
2 Jack 20 [email protected]
3 Tom 28 [email protected]
4 Sandy 21 [email protected]
5 Billie 24 [email protected]

其对应的数据库 Schema 脚本和 Data 脚本如下:

-- 创建数据库
CREATE DATABASE mybatis_plus;

-- 使用数据库
USE mybatis_plus;

-- 创建数据库表
DROP TABLE IF EXISTS USER;
CREATE TABLE USER
(
	id BIGINT(20) NOT NULL COMMENT '主键ID',
	NAME VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);

-- 插入测试数据
DELETE FROM USER;
INSERT INTO USER (id, NAME, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');

Question:如果从零开始用 MyBatis-Plus 来实现该表的增删改查我们需要做什么呢?

2、引入依赖

引入 Spring Boot Starter 作为当前工程的父工程:

<parent>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-parentartifactId>
    <version>2.2.2.RELEASEversion>
parent>

引入 spring-boot-starterspring-boot-starter-testmybatis-plus-boot-startermysql 依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
    dependency>
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
    dependency>
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
    dependency>
    <dependency>
        <groupId>com.baomidougroupId>
        <artifactId>mybatis-plus-boot-starterartifactId>
        <version>3.4.2version>
    dependency>
dependencies>

3、创建实体类以及 Mapper 映射接口

创建 User 实体类:实体类的字段最好使用包装类型,而不要使用基本类型。因为每个基本类型都有一个默认值,在查询的时候,就不好区分是数据库记录的值,还是字段的默认值。但是包装类型没有,如果没有为包装类型设置值,那么其值为 null

/**
 * @Author Oneby
 * @Date 2021/4/18 17:53
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private Long id;
    private String name;
    private Integer age;
    private String email;

}

创建 UserMapper 映射接口,该接口继承了 BaseMapper 接口

/**
 * @Author Oneby
 * @Date 2021/4/18 17:53
 */
@Repository
public interface UserMapper extends BaseMapper<User> {

}

4、创建主启动类

在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 接口所在的包

/**
 * @Author Oneby
 * @Date 2021/4/18 17:51
 */
@SpringBootApplication
@MapperScan("com.oneby.mapper")
public class MybatisPlusApplication {

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

}

5、编写配置文件

在 application.yml 配置文件中配置数据源信息。注意:低版本 MySQL 驱动为 com.mysql.jdbc.Driver,无需配置时区;高版本 MySQL 驱动为 com.mysql.cj.jdbc.Driver,需要增加时区的配置

# 数据源配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3307/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: root

6、代码测试

编写测试代码

  1. @RunWith(SpringRunner.class):这是 junit 提供的注解,该注解让测试运行于Spring测试环境,并让 SpringRunner 这个类提供 Spring 测试上下文
  2. @SpringBootTest:SpringBoot 测试类的注解,该注解会启动 SpringBoot 应用,并在测试中创建 ApplicationContext 对象
  3. UserMapper 中的 selectList() 方法的参数为 MP 内置的条件封装器 Wrapper,所以不填写就是无任何条件
/**
 * @Author Oneby
 * @Date 2021/4/18 17:54
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class MybatisPlusEnvironmentTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSelect() {
        List<User> userList = userMapper.selectList(null);
        userList.forEach(System.out::println);
    }

}

程序运行结果:通过以上几个简单的步骤,我们就实现了 User 表的 CRUD 功能,甚至连 XML 文件都不用编写!

User(id=1, name=Jone, age=18, [email protected])
User(id=2, name=Jack, age=20, [email protected])
User(id=3, name=Tom, age=28, [email protected])
User(id=4, name=Sandy, age=21, [email protected])
User(id=5, name=Billie, age=24, [email protected])

2.2、SQL 日志

查看 SQL 日志

为了能够观察调用每个方法时,MybatisPlus 到底为我们做了什么?执行了什么样的 SQL 语句?我们就需要开启 SQL 日志

# SQL 日志配置
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

开启日志之后,再次运行测试代码,可以看到调用 Mapper 方法时执行的 SQL 语句

DBC Connection [HikariProxyConnection@81505591 wrapping com.mysql.cj.jdbc.ConnectionImpl@7b4acdc2] will not be managed by Spring
==>  Preparing: SELECT id,name,age,email FROM user
==> Parameters: 
<==    Columns: id, name, age, email
<==        Row: 1, Jone, 18, [email protected]
<==        Row: 2, Jack, 20, [email protected]
<==        Row: 3, Tom, 28, [email protected]
<==        Row: 4, Sandy, 21, [email protected]
<==        Row: 5, Billie, 24, [email protected]
<==      Total: 5
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@52a70627]
User(id=1, name=Jone, age=18, [email protected])
User(id=2, name=Jack, age=20, [email protected])
User(id=3, name=Tom, age=28, [email protected])
User(id=4, name=Sandy, age=21, [email protected])
User(id=5, name=Billie, age=24, [email protected])

2.3、提出问题

我们都没有编写过CRUD 的接口以及实现,怎么就能执行基本的增删改查了呢?

我们自己编写的 UserMapper 类继承自 BaseMapper 接口,该接口中提供了基本的增删改查方法,因此我们自己编写的 Mapper 接口只需要继承 BaseMapper 父接口,就能获得基本的增删改查功能

/**
 * Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
 * 

这个 Mapper 支持 id 泛型

* * @author hubin * @since 2016-01-23 */
public interface BaseMapper<T> extends Mapper<T> { /** * 插入一条记录 * * @param entity 实体对象 */ int insert(T entity); /** * 根据 ID 删除 * * @param id 主键ID */ int deleteById(Serializable id); /** * 根据 columnMap 条件,删除记录 * * @param columnMap 表字段 map 对象 */ int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); /** * 根据 entity 条件,删除记录 * * @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) */ int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); /** * 删除(根据ID 批量删除) * * @param idList 主键ID列表(不能为 null 以及 empty) */ int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); /** * 根据 ID 修改 * * @param entity 实体对象 */ int updateById(@Param(Constants.ENTITY) T entity); /** * 根据 whereEntity 条件,更新记录 * * @param entity 实体对象 (set 条件值,可以为 null) * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) */ int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper); /** * 根据 ID 查询 * * @param id 主键ID */ T selectById(Serializable id); /** * 查询(根据ID 批量查询) * * @param idList 主键ID列表(不能为 null 以及 empty) */ List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); /** * 查询(根据 columnMap 条件) * * @param columnMap 表字段 map 对象 */ List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); /** * 根据 entity 条件,查询一条记录 * * @param queryWrapper 实体对象封装操作类(可以为 null) */ T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); /** * 根据 Wrapper 条件,查询总记录数 * * @param queryWrapper 实体对象封装操作类(可以为 null) */ Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); /** * 根据 entity 条件,查询全部记录 * * @param queryWrapper 实体对象封装操作类(可以为 null) */ List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); /** * 根据 Wrapper 条件,查询全部记录 * * @param queryWrapper 实体对象封装操作类(可以为 null) */ List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); /** * 根据 Wrapper 条件,查询全部记录 *

注意: 只返回第一个字段的值

* * @param queryWrapper 实体对象封装操作类(可以为 null) */
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); /** * 根据 entity 条件,查询全部记录(并翻页) * * @param page 分页查询条件(可以为 RowBounds.DEFAULT) * @param queryWrapper 实体对象封装操作类(可以为 null) */ <E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); /** * 根据 Wrapper 条件,查询全部记录(并翻页) * * @param page 分页查询条件 * @param queryWrapper 实体对象封装操作类 */ <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); }

诶,不对啊,BaseMapper 中之定义了接口,没有定义 SQL 语句呀。MybatisPlus 注入 SQL 的原理在后面会讲解,这里简单提一下。

我们以 Debug 的方式调试程序,找到 userMapper 中的 sqlSession --> sqlSessionFactory --> configuration --> mappedStatementsmappedStatements 的类型为 StrictMap,但其本质是 HashMapkeyString 类型,存储 Mapper 接口的方法名;valueMappedStatement 类型,存储接口方法对应的 SQL 信息。

第 1 章 MybatisPlus 快速入门_第2张图片

MappedStatement 中可以找到 com.oneby.mapper.UserMapper.selectById 方法对应的 SQL 语句为 SELECT id,name,age,email FROM user WHERE id=?,也就是 MybatisPlus 在加载 Mapper 接口时就已经帮我们创建好了其对应的 SQL 语句(这仅仅针对于能提前确定下来的简单 SQL 语句)

第 1 章 MybatisPlus 快速入门_第3张图片

对于 com.oneby.mapper.UserMapper.selectList 方法,其 SQL 语句不能提前确定下来,在 sqlSource 下就没有 sql 字段,取而代之的时 rootSqlNode 字段,该字段会根据条件构造器来动态拼接 SQL 语句

第 1 章 MybatisPlus 快速入门_第4张图片

你可能感兴趣的:(Mybatis,MybatisPlus)