MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发 提高效率而生。该框架由baomidou(苞米豆)组织开发并且开源的。
官 网 :https://mybatis.plus/或 https://mp.baomidou.com/
github 地 址 : https://github.com/baomidou/mybatis-plus 码云地址:https://gitee.com/baomidou/mybatis-plus
1.2 支持的数据库MyBatisPlus支持如下数据库:
mysql mariadb oracle db2 h2 hsql sqlite postgresql sqlserver
达梦数据库 虚谷数据库 人大金仓数据库
1.3 特性无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝滑
损耗小:启动即会自动注入基本 CRUD,性能基本无损耗,直接面向对象操作
强大的 CRUD 操作:内置通用 Mapper 通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作, 更有强大的条件构造器,满足各类使用需求
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
支持多种数据库:支持 MySQL MariaDB Oracle DB2 H2 HSQL SQLite Postgre SQLServer2005 SQLServer
等多种数据库
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题1
支持 XML 热加载:Mapper 对应的 XML 支持热加载,对于简单的 CRUD 操作,甚至可以无 XML 启动
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD
操作
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
支持关键词自动转义:支持数据库关键词(order key…)自动转义,还可自定义关键词
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper Model Service Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通
List 查询
内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
内置全局拦截插件:提供全表 delete update 操作智能分析阻断,也可自定义拦截规则,预防误操作
内置Sql 注入剥离器:支持 Sql 注入剥离,有效预防 Sql 注入攻击
1.4 架构Mybatis主要包含以下模块:
核心功能(core),基于Mybatis的封装,提供了Mybatis Plus的基础配置类与核心功能,如内置通用 Mapper,
Lambda 表达式查询等。
注解(annotation),提供了Mybatis Plus中注解的定义。
扩展功能**(extension)**,提供扩展及插件功能,包括分页插件 通用 Service扩展 性能分析插件等。
代码生成器(generator):通过代码生成器可以快速生成 Mapper接口 Entity实体类 Mapper XML Service
Controller 等各个模块的代码,极大的提升了开发效率。
执行流程:
(1)扫描注解Entity,反射提取注解信息如:表名称 字段名称等信息。
(2)分析注解信息并基于com.baomidou.mybatisplus.core.enums的SQL模板生成基本CRUD SQL。
(3)最后将这些SQL注入到Mybatis环境中。
因此Mybatis plus无需编写CRUD SQL语句,只需继承BaseMapper,魔术般的拥有了CRUD功能(通用CRUD)。
2 快速入门 2.1 准备环境-
JDK 8+
-
Maven 3.5.4
-
IDEA 2020.2
-
MySQL5.7
创建数据库并设置字符集为utf-8:
CREATE DATABASE `mp` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
创建表和测试数据:
‐‐ 创建测试表 CREATE TABLE `tb_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `user_name` varchar(20) NOT NULL COMMENT '用户名', `password` varchar(20) NOT NULL COMMENT '密码', `name` varchar(30) DEFAULT NULL COMMENT '姓名', `age` int(11) DEFAULT NULL COMMENT '年龄', `email` varchar(50) DEFAULT NULL COMMENT '邮箱', `birthday` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; ‐‐ 插入测试数据 INSERT INTO `tb_user`(`id`,`user_name`,`password`,`name`,`age`,`email`,`birthday`) VALUES (1,'zhangsan','123456','张三',18,'test1@yh.cn','2019-09-26 11:42:01'), (2,'lisi','123456','李四',20,'test2@yh.cn','2019-10-01 11:42:08'), (3,'wangwu','123456','王五',28,'test3@yh.cn','2019-10-02 11:42:14'), (4,'zhaoliu','123456','赵六',21,'test4@yh.cn','2019-10-05 11:42:18'), (5,'sunqi','123456','孙七',24,'test5@yh.cn','2019-10-14 11:42:23');2.3 工程搭建 2.3.1 创建工程
创建maven工程,分别填写GroupId ArtifactId和Version,如下:
2.3.2 导入依赖yh.mp yh‐mp‐springboot1.0‐SNAPSHOT
导入maven依赖,由于本例采用Spring boot技术,使用mybatis-plus-boot-starter能与其便捷集成:
版本规划:
Spring boot: 2.2.10.RELEASE
mybatis-plus: 3.1.0
2.3.3 编写application.yaml4.0.0 org.springframework.boot spring-boot-starter-parent2.2.10.RELEASE com.glls.mp glls-mp-sb1.0-SNAPSHOT org.springframework.boot spring-boot-starterorg.springframework.boot spring-boot-starter-testtest org.projectlombok lomboktrue com.baomidou mybatis-plus-boot-starter3.1.0 mysql mysql-connector-java8.0.21
spring:
application:
name: laojun-mp-sb
datasource:
password: 123456
username: root
driver‐class‐name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
logging:
level:
root: debug
2.3.4 编写pojo
package com.glls.mp.pojo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_user")
public class User {
@TableId("ID")
private Long id;
@TableField("USER_NAME")
private String userName; //驼峰命名,则无需注解
@TableField("PASSWORD")
private String password;
@TableField("NAME")
private String name;
@TableField("AGE")
private Integer age;
@TableField("EMAIL")
private String email;
@TableField("BIRTHDAY")
private LocalDateTime birthday;
}
@Data:lombok的注解,使用它可以省略getter/setter方法。
@NoArgsConstructor: 生成无参构造 方法
@AllArgsConstructor:生成所有参数构造 方法,参数顺序与属性定义顺序一致。
@TableName:指定表名
@TableId:指定主键名
@TableField:指定列名
2.3.5 编写mapperpackage com.glls.mp.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.glls.mp.pojo.User; public interface UserMapper extends BaseMapper2.3.6 编写启动类{ }
package com.glls.mp;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.glls.mp.mapper")
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class,args);
}
}
2.3.7 编写测试用例
编写UserMapper的测试用例 ,使用UserMapper查询用户列表。在test下创建测试类,包名为 cn.yh.mp。
package com.glls.mp.testmp;
import com.glls.mp.mapper.UserMapper;
import com.glls.mp.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.List;
@SpringBootTest
public class UserMapperTest {
@Resource
private UserMapper userMapper;
@Test
public void testSelect() {
List userList = userMapper.selectList(null);
for (User user : userList) {
System.out.println(user);
}
}
}
测试:
2021-02-19 14:50:15.339 DEBUG 1360 --- [ main] c.glls.mp.mapper.UserMapper.selectList : ==> Preparing: SELECT ID,USER_NAME,PASSWORD,NAME,AGE,EMAIL,BIRTHDAY FROM tb_user 2021-02-19 14:50:15.374 DEBUG 1360 --- [ main] c.glls.mp.mapper.UserMapper.selectList : ==> Parameters: 2021-02-19 14:50:15.412 DEBUG 1360 --- [ main] c.glls.mp.mapper.UserMapper.selectList : <== Total: 5 2021-02-19 14:50:15.413 DEBUG 1360 --- [ main] org.mybatis.spring.SqlSessionUtils : Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7afb1741] User(id=1, userName=zhangsan, password=123456, name=张三, age=18, email=test1@yh.cn, birthday=2019-09-26T11:42:01) User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@yh.cn, birthday=2019-10-01T11:42:08) User(id=3, userName=wangwu, password=123456, name=王五, age=28, email=test3@yh.cn, birthday=2019-10-02T11:42:14) User(id=4, userName=zhaoliu, password=123456, name=赵六, age=21, email=test4@yh.cn, birthday=2019-10-05T11:42:18) User(id=5, userName=sunqi, password=123456, name=孙七, age=24, email=test5@yh.cn, birthday=2019-10-14T11:42:23)3 常见配置
在MP中有大量的配置,其中有一部分是Mybatis原生的配置,另一部分是MP的配置,详情:
https://mybatis.plus/config/
下面我们对常用的配置做讲解。
3.1 configLocationsconfigLocations即MyBatis 配置文件位置,如果您有单独的 MyBatis 配置,请将其路径配置到 configLocation
中。 MyBatis Configuration 的具体内容请参考MyBatis 官方文档
示例:
1 在resources下创建mybatis-config.xml
2 在application.yml下配置configLocations,如下:
spring: application: name: glls-mp-sb datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/mp?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true username: root password: 123456 logging: level: root: debug mybatis-plus: config-location: classpath:mybatis-config.xml mapper-locations: classpath*:mybatis/mapper int insert(T entity);4.1.2 测试用例
package cn.yh.mp;
import cn.yh.mp.mapper.UserMapper;
import cn.yh.mp.pojo.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testInsert() {
User user = new User();
user.setAge(20);
user.setEmail("test@yh.cn");
user.setName("曹操");
user.setUserName("caocao");
user.setPassword("123456");
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy‐MM‐dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.parse("1990‐01‐01 00:00:00", df);
user.setBirthday(localDateTime);
int result = this.userMapper.insert(user); //返回的result是受影响的行数,并不是自增后的id
System.out.println("result = " + result);
System.out.println(user.getId()); //自增后的id会回填到对象中
}
4.1.3 MP****主键生成策略
上例中Mybatis-plus自动生成ID,如何设置id的生成策略呢?
MP支持的id策略如下:
package com.baomidou.mybatisplus.annotation;
import lombok.Getter;
@Getter
public enum IdType {
AUTO(0),
NONE(1),
INPUT(2),
ID_WORKER(3),
UUID(4),
ID_WORKER_STR(5);
private final int key;
IdType(int key) {
this.key = key;
}
}
1 自增主键:
完全采用数据库自增主键方式。
1)设置mysql数据库主键为自增
2)修改User对象:
@TableId(value = "ID", type = IdType.AUTO) private Long id; 或: @TableId(value = "ID") private Long id;
3)程序中不用设置主键
2 输入主键:
手动设置主键值。
1)mysql数据库主键为自增或不是自增都可以
2)修改User对象:
@TableId(value = "ID",type = IdType.INPUT) private Long id;
3)程序中需要设置主键
3 UUID:
生成全局唯一ID。
1)mysql数据库主键为字符串类型,不是自增类型。
2)修改User对象。
@TableId(value = "ID",type = IdType.UUID) private String id;
3)程序中不用设置主键
4 ID_WORKER_STR:
采用雪花片算法(雪花算法生成的ID是纯数字且具有时间顺序,适合分布式场景)生成全局唯一ID,字符串类型。
1)mysql数据库主键为字符串类型,不是自增类型。
2)修改User对象。
@TableId(value = "ID",type = IdType.ID_WORKER_STR) private String id;
3)程序中不用设置主键
5 ID_WORKER:
采用雪花片算法生成全局唯一ID,数值类型。
1)mysql数据库主键为数值类型,不是自增类型。
2)修改User对象。
@TableId(value = "ID",type = IdType.ID_WORKER) private Long id;
3)程序中不用设置主键
4.2 更新操作 4.2.1 根据id更新方法定义:
int updateById(@Param(Constants.ENTITY) T entity);
根据id更新操作步骤:
1 首先需要设置对象的主键属性值。
2 再设置要更新的属性值。
3 根据主键找到对象,更新设置属性值。
4 返回影响的记录数。
注意:只能将对象中不为NULL的属性更新到表中。测试:
// 根据id 更新
@Test
public void testUpdateById() {
User user = new User();
user.setId(7L); //主键
user.setAge(21); //更新的字段
//根据id更新,更新不为null的字段
this.userMapper.updateById(user);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.updateById]‐[DEBUG] ==> Preparing: UPDATE tb_user SET age=? WHERe id=? [main] [cn.yh.mp.mapper.UserMapper.updateById]‐[DEBUG] ==> Parameters: 21(Integer), 6(Long) [main] [cn.yh.mp.mapper.UserMapper.updateById]‐[DEBUG] <== Updates: 14.2.2 根据条件更新
方法定义:
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) WrapperupdateWrapper);
根据ID更新一次只能更新一条记录,根据条件更新可实现批量更新。
根据条件更新步骤:
1 在对象中设置要更新的属性值。
2 设置QueryWrapper,设置更新条件,可以设置多个。
3 返回影响的记录数。
注意:只能将对象中不为NULL的属性更新到表中。测试用例:
下次将name等于“曹操”的记录全部更新。
@Test
public void testUpdate() {
User user = new User();
user.setAge(22); //更新的字段
//更新的条件
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq("name", "曹操");
//可以设置多个条件...
//执行更新操作 UPDATE tb_user SET age=22 WHERe name = '曹操'
int result = this.userMapper.update(user, wrapper);
System.out.println("result = " + result);
}
上边根据id更新 根据条件更新的方法只能将对象中不为NULL的属性更新到表中,下边通过UpdateWrapper进行更新,将birthday字段更新为NULL.
@Test
public void testUpdate2() {
//更新的条件以及字段
UpdateWrapper wrapper = new UpdateWrapper<>();
wrapper.eq("id", 7).set("age", 23).set("birthday",null);
//执行更新操作 UPDATE tb_user SET age=23,birthday=null WHERe id = 7
int result = this.userMapper.update(null, wrapper);
System.out.println("result = " + result);
}
4.3 删除操作
4.3.1 deleteById
方法定义:
int deleteById(Serializable id);
操作步骤:
1 指定要删除记录的主键值。
2 调用deleteById方法执行删除。
测试用例:
@Test
public void testDeleteById() {
//执行删除操作
int result = this.userMapper.deleteById(7L);
System.out.println("result = " + result);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.deleteById]‐[DEBUG] ==> Preparing: DELETE FROM tb_user WHERe id=? [main] [cn.yh.mp.mapper.UserMapper.deleteById]‐[DEBUG] ==> Parameters: 6(Long) [main] [cn.yh.mp.mapper.UserMapper.deleteById]‐[DEBUG] <== Updates: 14.3.2 delete
方法定义:
int delete(@Param(Constants.WRAPPER) Wrapperwrapper);
根据条件删除步骤:
1 定义对象,设置属性值,指定删除条件 ,可指定多个删除条件注意:删除条件只匹配对象中不为NULL的属性值
2 设置QueryWrapper
3 执行删除
测试用例:
// 根据条件删除
@Test
public void testDeleteByMap() {
User user = new User();
user.setAge(20);
user.setName("刘备");
//将实体对象进行包装,包装为操作条件
QueryWrapper wrapper = new QueryWrapper<>(user);
int result = this.userMapper.delete(wrapper);
System.out.println("result = " + result);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.delete]‐[DEBUG] ==> Preparing: DELETE FROM tb_user WHERe name=? AND age=? [main] [cn.yh.mp.mapper.UserMapper.delete]‐[DEBUG] ==> Parameters: 张三(String), 20(Integer) [main] [cn.yh.mp.mapper.UserMapper.delete]‐[DEBUG] <== Updates: 0
注意:
定义QueryWrapper可以不包装模型对象,手动设置条件,如下:
QueryWrapper4.3.3 deleteBatchIdswrapper = new QueryWrapper<>(); wrapper.eq("age",20); wrapper.eq("name","张三");
方法定义:
int deleteBatchIds(@Param(Constants.COLLECTION) Collection extends Serializable> idList);
批量删除操作步骤:
1 指定 id列表
2 执行删除
测试用例:
// 根据id 批量删除
@Test
public void testDeleteByIds() {
//根据id集合批量删除 DELETE FROM tb_user WHERe ID IN ( ? , ? , ? )
int result = this.userMapper.deleteBatchIds(Arrays.asList(1L,10L,20L));
System.out.println("result = "+ result);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.deleteBatchIds]‐[DEBUG] ==> Preparing: DELETE FROM tb_user WHERe id IN ( ? , ? , ? ) [main] [cn.yh.mp.mapper.UserMapper.deleteBatchIds]‐[DEBUG] ==> Parameters: 1(Long), 10(Long), 20(Long) [main] [cn.yh.mp.mapper.UserMapper.deleteBatchIds]‐[DEBUG] <== Updates: 14.4 查询操作
MP提供了多种查询操作,包括根据id查询 批量查询 查询单条数据 查询列表 分页查询等操作。
4.4.1 selectById方法定义:
T selectById(Serializable id);
根据id查询步骤:
1 设置查询记录的主键值。
2 执行查询。
3 查询结果返回一个对象。
测试用例:
// 根据id 查询
@Test
public void testSelectById() {
//根据id查询数据
User user = this.userMapper.selectById(2L);
System.out.println("result = " + user);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.selectById]‐[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email FROM tb_user WHERe id=? [main] [cn.yh.mp.mapper.UserMapper.selectById]‐[DEBUG] ==> Parameters: 2(Long) [main] [cn.yh.mp.mapper.UserMapper.selectById]‐[DEBUG] <== Total: 1 result = User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@yh.cn, address=null)4.4.2 selectBatchIds
方法定义:
ListselectBatchIds(@Param(Constants.COLLECTION) Collection extends Serializable> idList);
根据id列表查询:
1 设置id列表
2 执行查询
3 查询对象返回List
测试用例:
// 根据多个id 查询
@Test
public void testSelectBatchIds() {
//根据id集合批量查询
List users = this.userMapper.selectBatchIds(Arrays.asList(2L, 3L, 10L));
for (User user : users) {
System.out.println(user);
}
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.selectBatchIds]‐[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email FROM tb_user WHERe id IN ( ? , ? , ? ) [main] [cn.yh.mp.mapper.UserMapper.selectBatchIds]‐[DEBUG] ==> Parameters: 2(Long), 3(Long), 10(Long) [main] [cn.yh.mp.mapper.UserMapper.selectBatchIds]‐[DEBUG] <== Total: 2 User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@yh.cn, address=null) User(id=3, userName=wangwu, password=123456, name=王五, age=28, email=test3@yh.cn, address=null)4.4.3 selectOne
方法定义:
T selectOne(@Param(Constants.WRAPPER) WrapperqueryWrapper);
查询步骤:
1 设置QueryWrapper对象,设置查询条件,可以设置多个条件
2 执行查询
注意:如果查询结果为多条记录则报错(TooManyResultsException)。
测试用例:
// 查询 返回一条结果
@Test
public void testSelectOne() {
QueryWrapper wrapper = new QueryWrapper(); wrapper.eq("name", "李四");
//根据条件查询一条数据,如果结果超过一条会报错
User user = this.userMapper.selectOne(wrapper);
System.out.println(user);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.selectOne]‐[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email FROM tb_user WHERe name = ? [main] [cn.yh.mp.mapper.UserMapper.selectOne]‐[DEBUG] ==> Parameters: 李四(String) [main] [cn.yh.mp.mapper.UserMapper.selectOne]‐[DEBUG] <== Total: 1 User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@yh.cn, address=null)4.4.4 selectCount
方法定义:
Integer selectCount(@Param(Constants.WRAPPER) WrapperqueryWrapper);
测试用例:
// 查询记录数
@Test
public void testSelectCount() {
QueryWrapper wrapper = new QueryWrapper(); wrapper.gt("age", 23); //年龄大于23岁
//根据条件查询数据条数
Integer count = this.userMapper.selectCount(wrapper);
System.out.println("count = " + count);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.selectCount]‐[DEBUG] ==> Preparing: SELECT COUNT( 1 ) FROM tb_user WHERe age > ? [main] [cn.yh.mp.mapper.UserMapper.selectCount]‐[DEBUG] ==> Parameters: 23(Integer) [main] [cn.yh.mp.mapper.UserMapper.selectCount]‐[DEBUG] <== Total: 1 count = 24.4.5 selectList
方法定义:
ListselectList(@Param(Constants.WRAPPER) Wrapper queryWrapper);
测试用例
@Test
public void testSelectList() {
QueryWrapper wrapper = new QueryWrapper();
wrapper.gt("age", 23); //年龄大于23岁
//根据条件查询数据
List users = this.userMapper.selectList(wrapper);
for (User user : users) {
System.out.println("user = " + user);
}
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.selectList]‐[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email FROM tb_user WHERe age > ? [main] [cn.yh.mp.mapper.UserMapper.selectList]‐[DEBUG] ==> Parameters: 23(Integer) [main] [cn.yh.mp.mapper.UserMapper.selectList]‐[DEBUG] <== Total: 2 user = User(id=3, userName=wangwu, password=123456, name=王五, age=28, email=test3@yh.cn, address=null) user = User(id=5, userName=sunqi, password=123456, name=孙七, age=24, email=test5@yh.cn, address=null)4.4.6 selectPage
方法定义:
IPageselectPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper);
配置分页插件:
package com.laojun.mp.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor();
}
}
测试用例:
// 测试分页
@Test
public void testSelectPage() {
QueryWrapper wrapper = new QueryWrapper();
wrapper.gt("age", 20); //年龄大于20岁
//参数1:当前页码,小于1的按1算
//参数2:每页记录数
Page page = new Page<>(1,2);
//根据条件查询数据
IPage iPage = this.userMapper.selectPage(page, wrapper);
System.out.println("数据总条数:" + iPage.getTotal());
System.out.println("总页数:" + iPage.getPages());
//取出分页记录
List users = iPage.getRecords(); for (User user : users) {
System.out.println("user = " + user);
}
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.selectPage]‐[DEBUG] ==> Preparing: SELECT COUNT(1) FROM tb_user WHERe age > ? [main] [cn.yh.mp.mapper.UserMapper.selectPage]‐[DEBUG] ==> Parameters: 20(Integer) [main] [cn.yh.mp.mapper.UserMapper.selectPage]‐[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email FROM tb_user WHERe age > ? LIMIT ?,? [main] [cn.yh.mp.mapper.UserMapper.selectPage]‐[DEBUG] ==> Parameters: 20(Integer), 0(Long), 1(Long) [main] [cn.yh.mp.mapper.UserMapper.selectPage]‐[DEBUG] <== Total: 1 [main] [org.mybatis.spring.SqlSessionUtils]‐[DEBUG] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6ecd665] 数据总条数:3 总页数:3 user = User(id=3, userName=wangwu, password=123456, name=王五, age=28, email=test3@yh.cn, birthday=2019‐10‐02T11:42:14, address=null)5 条件构造器
在MP中,Wrapper接口的实现类关系如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J3XsksUS-1656753035817)(assets/clip_image118.jpg)]
在MP查询中,还可以使用lambda方式查询,降低数据库列表写错的风险。
5.1 基本比较操作eq
等于 =
ne
不等于 <>
gt
大于 >
ge
大于等于 >=
lt
小于 <
le
小于等于 <=
between
BETWEEN 值1 AND 值2
notBetween
NOT BETWEEN 值1 AND 值2
in
字段 IN (value.get(0), value.get(1), …)
notIn
字段 NOT IN (v0, v1, …)
测试用例:
@Test
public void testEq() {
QueryWrapper wrapper = new QueryWrapper<>();
//SELECT id,user_name,password,name,age,email FROM tb_user WHERe password = ? AND age >=? AND name IN (?,?,?)
wrapper.eq("password", "123456")
.ge("age", 20)
.in("name", "李四", "王五", "赵六");
List users = this.userMapper.selectList(wrapper);
for (User user : users) {
System.out.println(user);
}
}
Lambda方式构造条件:
LambdaQueryWrapperwrapper = new LambdaQueryWrapper<>(); //SELECT id,user_name,password,name,age,email FROM tb_user WHERe password = ? AND age >= ? AND name IN (?,?,?) wrapper.eq(User::getPassword, "123456") .ge(User::getAge, 20) .in(User::getName, "李四", "王五", "赵六"); List users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); }
通常在开发中要根据表达式进行判断,表达式为true则拼接条件,如下:
eq(boolean condition, R column, Object val) in(boolean condition, R column, Object... values) ...
一个例子:
//比如根据name来判断,如果name不为空则拼接条件String name = null; wrapper.eq(User::getPassword, "123456") .ge(User::getAge, 20) .in(name!=null,User::getName, "李四", "王五", "赵六");5.2 模糊查询
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ywpE7Ywc-1656753035817)(assets/image-20210128175722101.png)]
测试用例:
@Test
public void testWrapper() {
QueryWrapper wrapper = new QueryWrapper<>();
//SELECT id,user_name,password,name,age,email FROM tb_user WHERe name LIKE ?
//Parameters: % 五 %(String)
wrapper.like("name", "五");
List users = this.userMapper.selectList(wrapper);
for (User user : users) {
System.out.println(user);
}
}
Lambda方式构造条件:
LambdaQueryWrapper5.3 逻辑查询wrapper = new LambdaQueryWrapper<>(); wrapper.like(User::getName, "五");
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZwqfjBRO-1656753035818)(assets/image-20210128180125962.png)]
测试用例:
@Test
public void testWrapper2() {
QueryWrapper wrapper = new QueryWrapper<>();
//SELECT id,name,age FROM tb_user WHERe name = ? OR age = ?
wrapper.eq("name", "李四")
.or()
.eq("age", 24)
.select("id", "name", "age");
List users = this.userMapper.selectList(wrapper);
for (User user : users) {
System.out.println(user);
}
}
Lambda方式构造条件:
LambdaQueryWrapper5.4 selectwrapper = new LambdaQueryWrapper<>(); wrapper.eq(User::getName, "李四") .or() .eq(User::getAge, 24);
在MP查询中,默认查询所有的字段,如果有需要也可以通过select方法进行指定字段。
package cn.yh.mp;
import cn.yh.mp.mapper.UserMapper;
import cn.yh.mp.pojo.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testWrapper() {
QueryWrapper wrapper = new QueryWrapper<>();
//SELECT id,name,age FROM tb_user WHERe name = ? OR age = ?
wrapper.eq("name", "李四")
.or()
.eq("age", 24)
.select("id", "name", "age");
List users = this.userMapper.selectList(wrapper);
for (User user : users) {
System.out.println(user);
}
}
}
Lambda方式构造条件:
LambdaQueryWrapper5.5 排序wrapper = new LambdaQueryWrapper<>(); wrapper.eq(User::getName, "李四") .or() .eq(User::getAge, 24) .select(User::getId, User::getName, User::getAge);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-saw9u5r2-1656753035818)(assets/image-20210129142414191.png)]
orderBy(boolean condition, boolean isAsc, R... columns) ‐ 自定义排序规则 ‐ 参数1:true有效,false无效 ,参数2:是否升序,参数3..设置多个字段 ‐ 例: `orderBy(true, true, "id", "name")`‐‐‐>`order by id ASC,name ASC` ‐ 也可以多个orderBy拼装,如下: orderBy(true, true, "id").orderBy(true, true, "name") 效果同上
package cn.yh.mp;
import cn.yh.mp.mapper.UserMapper;
import cn.yh.mp.pojo.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testWrapper() {
QueryWrapper wrapper = new QueryWrapper<>();
//SELECT id,user_name,password,name,age,email FROM tb_user ORDER BY age DESC
wrapper.orderByDesc("age");
List users = this.userMapper.selectList(wrapper);
for (User user : users) {
System.out.println(user);
}
}
}
Lambda方式构造条件:
LambdaQueryWrapperwrapper = new LambdaQueryWrapper<>(); wrapper.orderByDesc(User::getAge);
t.println(user);
}
}
}
Lambda方式构造条件: ~~~java LambdaQueryWrapper5.5 排序wrapper = new LambdaQueryWrapper<>(); wrapper.eq(User::getName, "李四") .or() .eq(User::getAge, 24) .select(User::getId, User::getName, User::getAge);
[外链图片转存中…(img-saw9u5r2-1656753035818)]
orderBy(boolean condition, boolean isAsc, R... columns) ‐ 自定义排序规则 ‐ 参数1:true有效,false无效 ,参数2:是否升序,参数3..设置多个字段 ‐ 例: `orderBy(true, true, "id", "name")`‐‐‐>`order by id ASC,name ASC` ‐ 也可以多个orderBy拼装,如下: orderBy(true, true, "id").orderBy(true, true, "name") 效果同上
package cn.yh.mp;
import cn.yh.mp.mapper.UserMapper;
import cn.yh.mp.pojo.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testWrapper() {
QueryWrapper wrapper = new QueryWrapper<>();
//SELECT id,user_name,password,name,age,email FROM tb_user ORDER BY age DESC
wrapper.orderByDesc("age");
List users = this.userMapper.selectList(wrapper);
for (User user : users) {
System.out.println(user);
}
}
}
Lambda方式构造条件:
LambdaQueryWrapperwrapper = new LambdaQueryWrapper<>(); wrapper.orderByDesc(User::getAge);



