banner
NEWS LETTER

MyBatis Plus

Scroll down

1 MyBatis Plus 简介

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

谁适合阅读本教程?

本教程适合所有学习过 mybatis(能熟练使用 mybatis,否则体会不到它的方便和高效),但是需要对 mybatis-plus 了解和应用的同学。

特性

· 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

· 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作

· 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求

· 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题

· 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用

· 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询

· 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库

mybatis plus中实现对象封装操作类,他的层级关系如下:

img

Wrapper : 条件构造抽象类,最顶端父类,抽象类中提供4个方法西面贴源码展示
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
AbstractLambdaWrapper : Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。
LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper : Lambda 更新封装Wrapper
QueryWrapper : Entity 对象封装操作类,不是用lambda语法
UpdateWrapper : Update 条件封装,用于Entity对象更新操作

2 环境搭建

1 导入依赖

1
2
3
4
5
6
<!--mybatis-plus依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>

2 配置数据源和sql,sql打印, 映射文件配置

1
2
3
4
5
6
7
8
9
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/java210302?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
spring.datasource.username=root
spring.datasource.password=1234

#sql 打印
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#mybatis-plus的 sql映射文件配置
mybatis-plus.mapper-locations=classpath:mapper/*.xml

3 BaseMapper 接口简介

课堂演示 数据表的表结构

DROP TABLE IF EXISTS user_info;

CREATE TABLE user_info (

user_id int(11) NOT NULL auto_increment,

user_name varchar(40) default NULL,

user_pwd varchar(40) default NULL,

user_detail_id int(11) default NULL,

PRIMARY KEY (user_id)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

定义pojo 类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Data
@TableName("user_info")
public class UserInfo extends MyPage implements Serializable {

private static final long serialVersionUID=1L;

@TableId(value = "user_id", type = IdType.AUTO)
private Integer userId;

private String userName;

private String userPwd;

private String userDetailId;


}

1 @TableName 注解用来将指定的数据库表和 JavaBean 进行映射。

2 @TableId 注解的用法,该注解用于将某个成员变量指定为数据表主键.

​ value指定数据表主键字段名称,不是必填的,默认为空字符串

​ type 指定数据表主键类型,如:ID自 增、UUID等。该属性的值是一个 IdType 枚举类型,默认为 IdType.NONE。

​ AUTO 数据库 ID 自增。如果我们创建数据库表时使用了 AUTO_INCREMENT 修饰主键

3 @TableField 字段注解,该注解用于标识非主键的字段。将数据库列与 JavaBean 中的属性进行映射,例如:

​ exist 是否为数据库表字段,默认为 true。

定义BaseMapper接口

例如:

1
2
3
4
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}


你会发现,我们在 UserInfoMapper中没有声明任何方法。但是我们在 UserInfoMapper测试类中却使用了 insert()、selectById()、updateById() 和 deleteById() 方法。而这些方法均来至 BaseMapper 接口

Insert保存数据

1
2
3
4
5
6
7
8
9
//insert新增
@Test
public void add(){
UserInfo user = new UserInfo();
user.setUserName("lisi");
user.setUserPwd("123");
int num = userInfoMapper.insert(user);
System.out.println("num="+num);
}

Update修改数据

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
//根据id修改
@Test
public void update(){
UserInfo user = new UserInfo();
//定义修改的值
user.setUserName("admin");
user.setUserPwd("123");
//定义修改条件的id
user.setUserId(1);
int num = userInfoMapper.updateById(user);
System.out.println("num="+num);

}
//根据自定义条件修改
@Test
public void update02(){
//创建修改对象
UpdateWrapper<UserInfo> wrapper = new UpdateWrapper<>();
//定义修改条件
wrapper.ge("user_id",1);
//创建要修改的值
UserInfo user = new UserInfo();
user.setUserPwd("123");
int num = userInfoMapper.update(user,wrapper);
System.out.println("num="+num);

}

Delete删除数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//根据id删除
@Test
public void del01(){
int rs = userInfoMapper.deleteById(6);
}
//根据 Wrapper 查询对象删除数据
@Test
public void del02(){
//定义查询对象
QueryWrapper<UserInfo> w = new QueryWrapper<>();
w.ge("user_id",8);
int rs = userInfoMapper.delete(w);
}
//批量删除数据
@Test
public void del03(){
//定义要删除的id集合
List<Integer> ids = Arrays.asList(3,4,6);
int rs = userInfoMapper.deleteBatchIds(ids);
System.out.println("rs="+rs);

}

Select查询数据

根据id查询

1
2
3
4
5
6
7
//根据id查询
@Test
public void search01(){
UserInfo u = userInfoMapper.selectById(1);
System.out.println(u.toString());
}

Wrapper 查询且只返回一条记录

1
2
3
4
5
6
7
8
//根据 Wrapper 查询,且只返回一条记录
@Test
public void search02(){
QueryWrapper<UserInfo> w = new QueryWrapper<>();
w.eq("user_id",1);
UserInfo u = userInfoMapper.selectOne(w);
System.out.println(u.toString());
}

Wrapper 查询且只返回多条记录

1
2
3
4
5
6
7
8
//根据 Wrapper 查询,返回多条记录
@Test
public void search03(){
QueryWrapper<UserInfo> w = new QueryWrapper<>();
w.ge("user_id",1);
List<UserInfo> listu = userInfoMapper.selectList(w);
System.out.println(listu.size());
}

批量查询

1
2
3
4
5
6
7
8
//批量查询
@Test
public void search04(){
//定义要查询的id集合
List<Integer> ids = Arrays.asList(3,4,6);
List<UserInfo> listu = userInfoMapper.selectBatchIds(ids);
System.out.println(listu.size());
}

动态查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//动态查询
@Test
public void search05(){
//定义要传入的参数
Integer queryId=1;
String queryName=null;

QueryWrapper<UserInfo> w = new QueryWrapper<>();
// 第一个参数为是否执行条件,为true则执行该条件
// 下面实现根据 user_id 和 user_name 动态查询
w.eq(queryId!=null,"user_id",queryId);
w.eq(StringUtils.isEmpty(queryName)&&queryName!=null,"user_name",queryName);
//查询结果
List<UserInfo> listu = userInfoMapper.selectList(w);
System.out.println(listu.size());
}

分页查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//分页查询
@Test
public void search06(){
//定义分页对象(1表示第一页;2表示每页大小为2)
Page<UserInfo> page = new Page<>(1,2);
//定义查询条件
QueryWrapper<UserInfo> w = new QueryWrapper<>();
//查询分页结果对象
Page<UserInfo> pageList = userInfoMapper.selectPage(page,w);
System.out.println("每页集合" + pageList.getRecords());
System.out.println("总页数: " + pageList.getPages());
System.out.println("总条数: " + pageList.getTotal());

}

排序查询

1
2
3
4
5
6
7
8
9
10
11
12
//排序查询
@Test
public void search07(){
QueryWrapper<UserInfo> w = new QueryWrapper<>();
w.ge("user_id",1);
//降序
w.orderByDesc("user_id");
List<UserInfo> listu = userInfoMapper.selectList(w);
for(UserInfo u:listu){
System.out.println(u.toString());
}
}

一对一分页查询

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
需求:完成一对一查询,userinfo用户表和userdetail用户详细信息表是一对一关系
完成根据userinfo的用户id作为查询条件查询
假设 userinfo用户表的外键是user_deatail_id

1 在userinfo的pojo类定义以userdetail作为数据类型的属性,并生成set,get方法
private UserDetail userDetail;

2 在userInfoMapper接口中定义查询方法,注解和xml都可以,我这里用的是注解,代码如下:

//一对一查询
@Select("SELECT * from user_info where user_id > #{userId} ")
@Results(id="userInfoResultMap",value = {
@Result(column = "user_id",property = "userId"),
@Result(column = "user_name",property = "userName"),
@Result(column = "user_pwd",property = "userPwd"),
@Result(column = "user_detail_id",property="userDetail",
one = @One(select = "com.hqyj.mapper.UserDetailMapper.selectById")

),
})
Page<UserInfo> selectByOneAndOne(Page<UserInfo> page,@Param("userId") Integer userId);

3 测试
//一对一查询
@Test
public void search08(){
//定义分页对象(1表示第一页;2表示每页大小为2)
Page<UserInfo> page = new Page<>(1,2);

//查询分页结果对象
Page<UserInfo> pageList = userInfoMapper.selectByOneAndOne(page,1);
System.out.println("每页集合" + pageList.getRecords());
System.out.println("总页数: " + pageList.getPages());
System.out.println("总条数: " + pageList.getTotal());

}

一对多分页查询

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
需求:完成一对多分页查询,userinfo用户表和userLog用户日志表是一对多关系,
完成根据userLog日志表 的用户id作为查询
假设 userLog日志表的外键是uId

1 在userinfo的pojo类定义以List<userLog>作为数据类型属性,并生成set,get方法
private List<UserLog> userLogList;

2 在userLogMapper接口中定义查询方法,注解和xml都可以,我这里用的是注解,代码如下:
public interface UserLogMapper extends BaseMapper<UserLog> {
@Select("SELECT * from user_log where u_id= #{userId} ")
List<UserLog> selectListByUserId(Integer userId);
}

3 在userInfoMapper接口中定义查询方法,注解和xml都可以,我这里用的是注解,代码如下:
//一对多查询
@Select("SELECT * from user_info ")
@Results(id="ddd",value = {
@Result(column = "user_id",property = "userId"),
@Result(column = "user_name",property = "userName"),
@Result(column = "user_pwd",property = "userPwd"),
@Result(column = "user_id",property="userLogList",
many = @Many(select = "com.hqyj.mapper.UserLogMapper.selectListByUserId")
),
})
Page<UserInfo> selectByOneAndMore(Page<UserInfo> page);

4 测试
//一对多查询
@Test
public void search09(){
//定义分页对象(1表示第一页;2表示每页大小为2)
Page<UserInfo> page = new Page<>(1,2);

//查询分页结果对象
Page<UserInfo> pageList = userInfoMapper.selectByOneAndMore(page);
System.out.println("每页集合" + pageList.getRecords());
System.out.println("总页数: " + pageList.getPages());
System.out.println("总条数: " + pageList.getTotal());

}

4 条件构造器

img

本章节将介绍 eq(等于)和 ne(不等于)判断条件。

eq(等于 =)

1
eq(R column, ``Object` `val)``eq(``boolean` `condition, R column, ``Object` `val)

实例: 过滤 name 等于“张三”的用户信息

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``wrapper.eq(``"name"``, ``"张三"``); ``// 等价 SQL 语句:name = '张三'

ne(不等于 != 或 <>)

1
ne(R column, ``Object` `val)``ne(``boolean` `condition, R column, ``Object` `val)

实例:查询 name 不等于“张三”的用户信息

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``wrapper.ne(``"name"``, ``"张三"``);``// 等价的 SQL 语句: 或 name != '张三'

参数说明:

  • column:要用于条件筛选的数据库表列名称,如:name
  • val:用于指定数据表列的值,条件将根据该值进行筛选
  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件。

gt(大于 >)

1
gt(R column, ``Object` `val)``gt(``boolean` `condition, R column, ``Object` `val)

实例:查询 age 大于 18 岁

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``wrapper.gt(``"age"``, ``18``); ``// 等价 SQL 语句:age > 18

ge(大于等于 >=)

1
ge(R column, ``Object` `val)``ge(``boolean` `condition, R column, ``Object` `val)

实例:查询 age 大于等于 18 岁

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``wrapper.ge(``"age"``, ``18``); ``// 等价 SQL 语句:age >= 18

lt(小于 <)

1
lt(R column, ``Object` `val)``lt(``boolean` `condition, R column, ``Object` `val)

实例:查询 age 小于 18 岁

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``wrapper.lt(``"age"``, ``18``); ``// 等价 SQL 语句:age < 18

le(小于等于 <=)

1
le(R column, ``Object` `val)``le(``boolean` `condition, R column, ``Object` `val)

实例:查询 age 小于等于 18 岁

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``wrapper.le(``"age"``, ``18``); ``// 等价的 SQL 语句:age <= 18

参数说明:

  • column:要用于条件筛选的数据库表列名称,如:name
  • val:用于指定数据表列的值,条件将根据该值进行筛选
  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件

like(完全模糊,即“like ‘%val%’”)

1
like(R column, ``Object` `val)``like(``boolean` `condition, R column, ``Object` `val)

参数说明:

  • column:要用于条件筛选的数据库表列名称,如:name
  • val:用于指定数据表列的值,条件将根据该值进行筛选
  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件。

实例:查询用户名称中包含“王”值的用户信息,如下:

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``wrapper.like(``"name"``, ``"王"``); ``// 等价 SQL 语句:name like '%王%'

notLike(完全模糊取非,即“not like ‘%val%’”)

1
notLike(R column, ``Object` `val)``notLike(``boolean` `condition, R column, ``Object` `val)

参数说明:

  • column:要用于条件筛选的数据库表列名称,如:name
  • val:用于指定数据表列的值,条件将根据该值进行筛选
  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件。

实例:查询用户包含“王”值的用户信息,如下:

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``wrapper.notLike(``"name"``, ``"王"``); ``// 等价 SQL 语句:name not like '%王%'

likeLeft(仅左边模糊,即“like ‘%val’”)

1
likeLeft(R column, ``Object` `val)``likeLeft(``boolean` `condition, R column, ``Object` `val)

参数说明:

  • column:要用于条件筛选的数据库表列名称,如:name
  • val:用于指定数据表列的值,条件将根据该值进行筛选
  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件。

实例:查询用户名以“王”值结束的用户信息列表,如下:

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``wrapper.likeLeft(``"name"``, ``"王"``); ``// 等价 SQL 语句:name like '%王'

likeRight(仅右边模糊,即“like ‘val%’”)

1
likeRight(R column, ``Object` `val)``wrapper.likeRight(``boolean` `condition, R column, ``Object` `val)

参数说明:

  • column:要用于条件筛选的数据库表列名称,如:name
  • val:用于指定数据表列的值,条件将根据该值进行筛选
  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件。

实例:查询用户名以“王”值开始的用户信息列表,如下:

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``likeRight(``"name"``, ``"王"``); ``// 等价 SQL 语句:name like '王%'

isNull(字段 IS NULL)

1
isNull(R column)``isNull(``boolean` `condition, R column)

参数说明:

  • column:字段名
  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件。

isNotNull(字段 IS NOT NULL)

1
isNotNull(R column)``isNotNull(``boolean` `condition, R column)

参数说明:

  • column:字段名
  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件。

实例:构造 name 为空,或者 name 不为空的查询条件,如下:

1
2
QueryWrapper<UserBean> wrapper = new QueryWrapper<>();wrapper.isNull("name"); // 等价 SQL 语句:name is null` 
`QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``wrapper.isNotNull(``"name"``); ``// 等价 SQL 语句:name is not nu

orderByAsc(实现递增排序)

1
orderByAsc(R... columns)``orderByAsc(``boolean` `condition, R... columns)

参数说明:

  • columns:列名称,可以指定多个
  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件

实例:根据用户 ID 和 年龄递增排序。

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``wrapper.orderByAsc(``"user_id"``, ``"age"``);

orderByDesc(实现递减排序)

1
orderByDesc(R... columns)``orderByDesc(``boolean` `condition, R... columns)

参数说明:

  • columns:列名称,可以指定多个
  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件

实例:根据用户 ID 和 年龄递减排序。

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``wrapper.orderByDesc(``"user_id"``, ``"age"``);

orderBy(自定义排序方式)

1
orderBy(``boolean` `condition, ``boolean` `isAsc, R... columns)

参数说明:

  • columns:列名称,可以指定多个
  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件
  • isAsc:是否使用 ASC 排序,即递增排序;否则,则使用递减(DESC)排序

实例:根据用户 ID 和 年龄递减排序。

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrappe

group by 分组

groupBy 实现分组,groupBy 函数定义如下:

1
groupBy(R... columns)``groupBy(``boolean` `condition, R... columns)

参数说明:

  • columns:要分组的数据表列名称列表
  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件。

实例:用户信息表根据 sex 和 age 列进行分组,如下:

1
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();``wrapper.groupBy(``"sex"``, ``"age"``);

运行上面代码,你实际上将执行如下 SQL 语句:

1
SELECT` `user_id,``name``,sex,age,face,salary,borthday ``FROM` `user` `GROUP` `BY` `sex,age

or(或,拼接SQL的 OR 语句)

1
or()``or(``boolean` `condition)

参数说明:

  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件。

注意:主动调用 or 表示紧接着下一个方法不是用 and 连接!(不调用or则默认为使用and连接)

实例:构建一个查询用户 id 等于1,或者用户名称为“张三”的查询条件,代码如下:

1
2
3
4
QueryWrapper<UserBean> wrapper = ``new` `QueryWrapper<>();`
`wrapper.eq("id",1);
`wrapper.or();
wrapper.eq(``"name"``,``"老王"``);

and

1
and(Consumer<Param> consumer)``and(``boolean` `condition, Consumer<Param> consumer)

参数说明:

  • consumer:构造查询条件的回调接口,你需要实现 accept 方法
  • condition:用于指定当前这个条件是否有效;如果为 true,则应用当前条件;如果为 false,则忽略当前条件
其他文章
cover
SSM框架搭建
  • 25/09/27
  • 15:00
  • 3.6k
  • 20
cover
Thymeleaf
  • 25/09/27
  • 15:00
  • 1k
  • 5
目录导航 置顶
  1. 1. 1 MyBatis Plus 简介
  2. 2. 2 环境搭建
  3. 3. 3 BaseMapper 接口简介
    1. 3.1. 定义pojo 类
    2. 3.2. 定义BaseMapper接口
    3. 3.3. Insert保存数据
    4. 3.4. Update修改数据
    5. 3.5. Delete删除数据
    6. 3.6. Select查询数据
      1. 3.6.1. 根据id查询
      2. 3.6.2. Wrapper 查询且只返回一条记录
      3. 3.6.3. Wrapper 查询且只返回多条记录
      4. 3.6.4. 批量查询
      5. 3.6.5. 动态查询
      6. 3.6.6. 分页查询
      7. 3.6.7. 排序查询
      8. 3.6.8. 一对一分页查询
      9. 3.6.9. 一对多分页查询
  4. 4. 4 条件构造器
    1. 4.0.1. eq(等于 =)
    2. 4.0.2. ne(不等于 != 或 <>)
    3. 4.0.3. gt(大于 >)
    4. 4.0.4. ge(大于等于 >=)
    5. 4.0.5. lt(小于 <)
    6. 4.0.6. le(小于等于 <=)
    7. 4.0.7. like(完全模糊,即“like ‘%val%’”)
    8. 4.0.8. notLike(完全模糊取非,即“not like ‘%val%’”)
    9. 4.0.9. likeLeft(仅左边模糊,即“like ‘%val’”)
    10. 4.0.10. likeRight(仅右边模糊,即“like ‘val%’”)
    11. 4.0.11. isNull(字段 IS NULL)
    12. 4.0.12. isNotNull(字段 IS NOT NULL)
    13. 4.0.13. orderByAsc(实现递增排序)
    14. 4.0.14. orderByDesc(实现递减排序)
    15. 4.0.15. orderBy(自定义排序方式)
    16. 4.0.16. group by 分组
    17. 4.0.17. or(或,拼接SQL的 OR 语句)
    18. 4.0.18. and