Mybatis-plus复习篇

[toc]

1.MyBatis-plus基础

1.1.mybatis-plus简介

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

MyBatis-plus官网:https://baomidou.com/

特点:

  1. 润物无声:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。
  2. 效率至上:只需简单配置,即可快速进行单表 CRUD 操作,从而节省大量时间。
  3. 丰富功能:代码生成、自动分页、逻辑删除、自动填充等功能一应俱全

1.2.基本使用

  1. 插入依赖

    1
    2
    3
    4
    5
    <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
    <version>3.5.7</version>
    </dependency>
  2. 配置文件,这里只配置了数据库,可以加上mybatis-plus加入相关配置,也可以单独创建一个java配置类,专门用于配置mybatis-plus

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # DataSource Config
    spring:
    datasource:
    driver-class-name: org.h2.Driver
    username: root
    password: test
    sql:
    init:
    schema-locations: classpath:db/schema-h2.sql
    data-locations: classpath:db/data-h2.sql
  3. 编写实体类

    1
    2
    3
    4
    5
    6
    7
    @Data
    public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
    }
  4. 编写Mapper接口类UserMapper

    1
    2
    3
    public interface UserMapper extends BaseMapper<User> {

    }

    要想让spring知道这个bean,有俩种方式

  5. 在Mapper接口上加上@Mapper注解,自动注入(推荐)

  6. 在启动类添加@MapperScan扫描注解,扫描Mapper文件夹

1.3.注解映射

上面实例中,实体类名与表名,包括属性名与字段名都是完全一致的,所以mybatis-plus是可以识别的。但在实际开发中,很有可能会出现表名与实体类名不一致,或者属性名与字段名不一致的情况。此时就需要使用注解来进行映射。

● @TableName:表名注解,标识实体类对应的表。
● @TableId:主键注解(可以使用 type=IdType.AUTO 形式指定主键生成策略)
● @TableField:字段注解(非主键)

一般在代码中,实体类应该跟数据库中字段名保持一致,这是规范做法

主键生成策略

主键生成策略类型描述
AUTO数据库 ID 自增
INPUTinsert 前自行 set 主键值
ASSIGN_ID分配 ID(主键类型为 Number(Long 和 Integer)或 String)
ASSIGN_UUID分配 UUID,主键类型为 String

使用对应策略时,要注意数据库中主键属性与对应策略保持一致,否则无法应用,如果第一次Snowflake生成之后删掉后面应用策略的时候还是生成Snowflake,需要把数据库对应表删除重新建

1.4.命名转换问题

在实际开发中,项目中的类名、属性名,包括数据库中的表名、字段名,这些命名要严格遵守规范。一般来说:

● 在数据库设计中,由于数据库不区分大小写,所以都采用下划线命名法。
● 在java中,类名都采用帕斯卡命名法(大驼峰),属性名都采用驼峰命名法。

在配置文件加入:

1
2
3
4
5
6
7
8
9
10
# mybatis-plus配置
mybatis-plus:
configuration:
# 驼峰命名
map-underscore-to-camel-case: true
# 日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
id-type: auto

可以开启mybatis-plus的驼峰命名
日志可以使运行时控制台打印输出的SQL语句

1.5.关闭命名转换功能

如果数据库中没有采用下划线命名法,那么可以在SpringBoot的application.yml配置文件中关闭此功能:

1
2
3
mybatis-plus:
configuration:
map-underscore-to-camel-case: false

默认开启

2.BaseMapper核心接口

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
* Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
*/
public interface BaseMapper<T> extends Mapper<T> {

/**
* 插入一条记录
* @param entity 实体对象
*/
int insert(T entity);

/**
* 根据 ID 删除
* @param id 主键ID
*/
int deleteById(Serializable id);

/**
* 根据实体(ID)删除
* @param entity 实体对象
*/
int deleteById(T entity);

/**
* 根据 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<?> 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 条件,查询一条记录
* <p>查询一条记录,例如 qw.last("limit 1") 限制取一条记录, 注意:多条数据会报异常</p>
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
default T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper) {
List<T> ts = this.selectList(queryWrapper);
if (CollectionUtils.isNotEmpty(ts)) {
if (ts.size() != 1) {
throw ExceptionUtils.mpe("One record is expected, but the query result is multiple records");
}
return ts.get(0);
}
return null;
}

/**
* 根据 Wrapper 条件,判断是否存在记录
* @param queryWrapper 实体对象封装操作类
* @return
*/
default boolean exists(Wrapper<T> queryWrapper) {
Long count = this.selectCount(queryWrapper);
return null != count && count > 0;
}

/**
* 根据 Wrapper 条件,查询总记录数
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Long 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 条件,查询全部记录
* <p>注意: 只返回第一个字段的值</p>
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

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

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

查看BaseMapper核心接口的源代码,这里详细说明了封装的增删改查方法