首页 > 其他分享 >MyBatis-Plus 条件查询器

MyBatis-Plus 条件查询器

时间:2022-09-30 11:03:40浏览次数:51  
标签:queryWrapper QueryWrapper 查询器 private email Plus user MyBatis id


MyBatis-Plus剩余内容

​本篇的主要代码依赖于之前的通用Mapper和通用Service篇​

前两个星期忙着转正的事情,比较忙。所以快两个周每太更新博客,这周末抓紧时间把剩余的MP的补完,在这里记录一下。


文章目录


​提示:以下是本篇文章正文内容,下面案例可供参考​

一、常用注解

在我们平时的日常开发中,会经常遇到我们的数据小伙伴们在数据库中所创建的 ​表名要与我们Java开发人员所建的domian层的类名有一个对应关系​,这往往在不同的公司都有着不同的要求。

打个比方:数据库表名 ​​t_user​​​-------- 后台domian的实体类名​​User​​。这样很明显会操做报错。

MyBatis-Plus 条件查询器_mybatis

所以我们的MyBtais-Plus为我们提供了一系列的注解,下面我们来正式学习他们

1.1 @TableName

在实体类上加上注解​​@TableName("t_user")​​,标识这个类所对应的表名是t_user,这样才可以成功映射到对应的字段。

@TableName("t_user")
public class User {
private Long id;
private String userName;
private Integer age;
private String email;
}

以上是通过注解的方式完成,我们也可以通过配置文件来设置

mybatis-plus:
configuration:
# 配置MyBatis日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
# 配置MyBatis-Plus操作表的默认前缀
table-prefix:

通过table_prefix设置前缀只适用于数据库表有前缀的,如果表名与实体类名差别甚远,则建议使用注解

1.2 @TableId

MyBatis-Plus在实现CRUD时,会默认将id作为主键列,并在插入数据时,默认是​​基于雪花算法的策略生成id​ASSIGN_ID

【产生的问题】

  • 若实体类和表中表示主键的不是id,而是其他字段 如何匹配
  • 怎样实现数据库中的自增策略

【对策】

在实体类中uid属性上通过​​@TableId将其标识为主键​​,即可成功执行SQL语句

@TableName("t_user")
public class User {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private String userName;
private Integer age;
private String email;
}

这里有必要说下,idType,这个​​IdType​​​是MyBatis-plus里面所提供的​​一种主键生成策略的枚举类​

【源码】

@Getter
public enum IdType {
/**
* 数据库ID自增
* <p>该类型请确保数据库设置了 ID自增 否则无效</p>
*/
AUTO(0),
/**
* 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
*/
NONE(1),
/**
* 用户输入ID
* <p>该类型可以通过自己注册自动填充插件进行填充</p>
*/
INPUT(2),

/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
/**
* 分配ID (主键类型为number或string),
* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(雪花算法)
*
* @since 3.3.0
*/
ASSIGN_ID(3),
/**
* 分配UUID (主键类型为 string)
* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-",""))
*/
ASSIGN_UUID(4);

private final int key;

IdType(int key) {
this.key = key;
}
}

也就是说MP提供了5种测类,下面简要的介绍其中的某些:

  • AUTO:​​ 数据库自增策略,​​注意,该类型请确保数据库设置了id自增, 否则无效 ​
  • NONE:MP set主键,雪花算法实现。就是如果传了id用传的,否则默认的雪花算法
  • INPUT:需要时开发者手动赋值,没写一样雪花算法自动生成
  • ASSIGN_ID:雪花算法,默认,与数据库id是否设置了自增无关

1.3 @TableField

TableField与TableId的区别就是:

  • TableField适用于解决非主键字段不匹配的情况,而且TableField还可以指定那个字段查询的时候不显示
  • TableId主要解决主键不匹配的情况
@TableName("t_user")
public class User {

// 处理主键相关的字段名不一致 以及设置主键自增策略
@TableId(value = "id", type = IdType.AUTO)
private Long id;

// 在mp种默认的设置可以将数据库中的字段名xxx_xxx转化为相应的驼峰命名
@TableField(value = "user_name")
private String userName;

@TableField(value = "age")
private Integer age;

// exist=false 表示查询时候不显示
@TableField(exist = false)
private String email;

}

当我们使用了​​@TableField(exist = false)​​则在查询的时候就不会显示查询出来的值

MyBatis-Plus 条件查询器_主键_02

1.4 @TableLogic

逻辑删除
在我们的日常开发中,会经常遇到这种逻辑删除的操做,因为这样仍然会在数据库中保存这条数据,防止后期如果还想用的话还可以找到。​​​我们要时刻铭记,数据的CUD操做,一定要谨慎,谨慎,再谨慎!!!​

如果我们的业务对数据的要求是可以恢复的,我们就要使用逻辑删除操做,一般我们就在数据库种加一个字段​​is_deleted​

  • ​物理删除​​:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据
  • ​逻辑删除​​:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
  • 使用场景:可以进行数据恢复
@TableName("t_user")
public class User {

// 处理主键相关的字段名不一致 以及设置主键自增策略
@TableId(value = "id", type = IdType.AUTO)
private Long id;

// 在mp种默认的设置可以将数据库中的字段名xxx_xxx转化为相应的驼峰命名
@TableField(value = "user_name")
private String userName;

@TableField(value = "age")
private Integer age;

@TableField(value = "email")
private String email;

// 逻辑删除 0 标识未删除 1表示删除了
@TableLogic
private Integer isDeleted;

}

MyBatis-Plus 条件查询器_主键_03

注意:当我们使用了逻辑删除则删除操作就变成了修改操作

  • 测试删除功能,真正执行的是修改
    ​​​UPDATE t_user SET is_deleted=1 WHERE id=? AND is_deleted=0​
  • 测试查询功能,被逻辑删除的数据默认不会被查询
    ​​​SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0​

二、条件构造器Wrapper

Wrapper在MyBatis-plus里面主要分为两种:一种适用于查询的 QueryWrapper;一种是用于修改的UpdateWrapper

MyBatis-Plus 条件查询器_mybatis_04

【继承关系】

  • Wrapper : 条件构造抽象类,最顶端父类
  • AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
  • QueryWrapper : 查询条件封装
  • UpdateWrapper : Update 条件封装
  • AbstractLambdaWrapper : 使用Lambda 语法
  • LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
  • LambdaUpdateWrapper : Lambda 更新封装Wrapper

这里主要就是介绍QueryWrapper和UpdateWrapper

2.1 QueryWrapper

MyBatis-Plus 条件查询器_数据库_05


上图是BaseMapper里面的关于参数是Warpper的方法,下面我们一一介绍:

2.1.1 组装查询条件selectCount

/**
* 测试wraper封装查询条件1
*
* @throws Exception
*/
@Test
public void testQuery5() {
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
// sql: SELECT COUNT( * ) FROM t_user WHERE is_deleted=0 AND (age BETWEEN ? AND
// ?)
queryWrapper.between("age", 18, 23);
Long list = userMapper.selectCount(queryWrapper);
System.out.println(list);
}

2.1.2 组装查询条件selectList

/**
* 测试wraper封装查询条件2
*
* @throws Exception
*/
@Test
public void testQuery9() {
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
// SELECT id,user_name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND
// (email IS NOT NULL AND email LIKE ?)
queryWrapper.isNotNull("email").like("email", "163.com");
List<User> list = userMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}

2.1.3 组装查询参数selectMaps

/**
* 测试wraper封装查询条件3
*
* @throws Exception
*/
@Test
public void testQuery10() {
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
// SELECT age,email,user_name FROM t_user WHERE is_deleted=0
queryWrapper.select("age", "email", "user_name");
List<Map<String, Object>> list = userMapper.selectMaps(queryWrapper);
list.forEach(System.out::println);
}

2.1.4 组装查询selectOne

/**
* 测试wraper封装查询条件4
*
* @throws Exception
*/
@Test
public void testQuery11() {
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
// SELECT age,email,user_name FROM t_user WHERE is_deleted=0 AND (user_name = ?)
queryWrapper.select("age", "email", "user_name");
queryWrapper.eq("user_name", "test");
User list = userMapper.selectOne(queryWrapper);
System.out.println(list);
}

根据上述的方法,我们可以很轻松地观察到,querywrapper里面封装了许多的方法就是用于设置我们的查询条件,而且比较通俗易懂,比如​​ge大于等于​​​,​​between介于​​等等,这里只演示这些,剩下的自己在开发中用到继续摸索。


2.1.5 调整条件优先级

注意:​​
​​​这里说明下如何调整参数的优先级​​,我们都知道在sql中可以通过()完成查询条件的优先级提升,那么在MP中如何操做???

【代码演示】
通过and方法,利用lambda表达式实现

@Test
public void testQuery7() throws Exception {
User user = new User();
// 将用户名中包含有a并且(年龄大于20或邮箱为null)的用户信息修改
user.setEmail("[email protected]");
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
// UPDATE t_user SET age=?, email=? WHERE (user_name LIKE ? AND (age > ? OR email IS NULL))
queryWrapper.like("user_name", "a")
.and(
i -> i.ge("age", 20)
.or()
.isNull("email"));
List<User> list = userMapper.selectList(queryWrapper);

list.forEach(System.out::println);
}

2.1.6 实现子查询inSql

@GetMapping("/queryZI")
public List<User> queryZI() {
// SELECT id,user_name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (id IN ( SELECT id FROM t_user WHERE id <=100))
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
queryWrapper.inSql("id", " SELECT id FROM t_user WHERE id <=100");
List<User> maps = userMapper.selectList(queryWrapper);
return maps;
}

MyBatis-Plus 条件查询器_数据库_06

2.2 UpdateWrapper

MyBatis-Plus 条件查询器_java_07

2.2.1 组装修改条件update

@Test
public void testUpdate2() throws Exception {
User user = new User();
user.setEmail("[email protected]");
UpdateWrapper<User> updateWrapper = new UpdateWrapper<User>();
updateWrapper.ge("age", 20).like("user_name", "a").or().isNull("email");
/**
* 根据 whereEntity 条件,更新记录
*
* @param entity 实体对象 (set 条件值,可以为 null) 修改的参数
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)条件参数
*/
int row = userMapper.update(user, updateWrapper);

log.info("删除数据={}条", row);
}

三、MyBatis-Plus分页插件

MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能

3.1 实现步骤

1️⃣添加配置类

/**
* MybatisPlus的分页插件配置类
* @author wangruoxian
*
*/
@Configuration
@MapperScan("com.wei.mapper")
public class MyBatisPlusPageConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

2️⃣ 测试

@GetMapping("/page")
public IPage<User> pageList(){
Page<User> page = new Page<User>(1,3);
// QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
// // 当前页码
// page.setCurrent(1);
// // 每页显示的条数
// page.setSize(5);
IPage<User> selectPage = userMapper.selectPage(page, null);
log.info("当前页数={}",selectPage.getCurrent());
log.info("总页数={}",selectPage.getPages());
selectPage.getRecords().forEach(System.out::println);
log.info("每页大小={}",selectPage.getSize());
log.info("总数据条数={}",selectPage.getTotal());
return selectPage;
}

MyBatis-Plus 条件查询器_java_08

四、通用枚举

表中的有些字段值是固定的,例如性别(男或女),此时我们可以使用MyBatis-Plus的通用枚举来实现

4.1 数据库表添加字段sex

MyBatis-Plus 条件查询器_字段_09

4.2 配置扫描通用枚举

# 配置扫描通用枚举
type-enums-package:

4.3 新建枚举类

@Getter
public enum SexEnum {
MALE(0,"男"),
FEMALE(1,"女");

@EnumValue
private Integer sexCode;

private String sexValue;

private SexEnum(Integer sexCode, String sexValue) {
this.sexCode = sexCode;
this.sexValue = sexValue;
}
}

4.3.1 @EnumValue注解

通用的枚举类注解,将数据库字段映射成实体类的枚举类型成员变量

将枚举改成成员变量和数据库的字段映射起来,根据数据库字段的值找到对应枚举的对象

4.4 测试

MyBatis-Plus 条件查询器_字段_10

五、多数据源

适用于多种场景:​​纯粹多库、 读写分离、 一主多从、 混合模式等​​,目前我们就来模拟一个纯粹多库的一个场景,其他场景类似

场景说明:
我们创建两个库,分别为:mybatis_plus(以前的库不动)与mybatis_plus_1(新建),将
mybatis_plus库的product表移动到mybatis_plus_1库,这样每个库一张表,通过一个测试用例
分别获取用户数据与商品数据,如果获取到说明多库模拟成功

5.1 创建数据库及表

CREATE DATABASE `mybatis_plus_slave` 
use `mybatis_plus_slave`;

CREATE TABLE t_product
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名称',
price INT(11) DEFAULT 0 COMMENT '价格',
version INT(11) DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY (id)
);

INSERT INTO product (id, NAME, price) VALUES (1, '外星人笔记本', 100);

5.2 引入依赖

<!-- 引入依赖 多数据源 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>

5.3 配置多数据源

注意

spring:
# 配置数据源信息
datasource:
dynamic:
# 设置默认的数据源或者数据源组,默认值即为master
primary: master
# 严格匹配数据源,默认false.true未匹配到指定数据源时抛异常,false使用默认数据源
strict: false
datasource:
master:
url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
slave_1:
url: jdbc:mysql://localhost:3306/mybatis_plus_1?characterEncoding=utf-8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456

5.4 创建新库中Product对应的类

此处省略domain,mapper,service,serviceImpl的创建
【controller层】

@RestController
@RequestMapping("/product")
@Api(value = "测试 ProductController 的接口", tags = "产品管理相关的接口", description = "product产品测试接口")
public class ProductController {

@Autowired
private IProductService IProductService;

@GetMapping("/list")
// @ApiOperation("查询所有商品的接口")
public List<Product> queryAllProduct(){
return IProductService.list();
}
}

MyBatis-Plus 条件查询器_字段_11


标签:queryWrapper,QueryWrapper,查询器,private,email,Plus,user,MyBatis,id
From: https://blog.51cto.com/u_14957231/5725629

相关文章

  • SpringBoot之Mybatis开启SQL记录和Pagehelper
    配置mybatismybatis:#mapper路径mapper-locations:classpath:mapper/*.xmlconfiguration:#日志输出log-impl:org.apache.ibatis.logging.stdout.StdO......
  • MyBatis
    1.概念Mybatis是一款半ORM(对象关系映射)的持久层框架,支持定制化SQL、存储过程以及高级映射。避免了几乎所有的JDBC代码和手动设置参数及获取结果集。可以使用注解或......
  • Mybatis学习
    什么是Mybatis?看官网的定义:MyBatis是一款优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的......
  • Mybatis(2022-09-29)
    SSMSpringMVC+Spring+Mybatis3SpringMVC:充当的就是Servlet的角色。可以理解为SpringMVC是Spring的WEB支持。1Mybatis:充当的就是Dao层。2Spring:充当的时一个润滑油......
  • springboot+mybatis 双数据源配置
    maven依赖spring-boot-starter-webmybatis-spring-boot-startermysql-connector-javalombokapplication.ymlserver:port:8080#启动端口spring:datasource:......
  • 05. MyBatis缓存
    一、MyBatis的一级缓存  一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问。  ......
  • mybatis 参数为String,用_parameter 取值
    mybatis参数为String,iftest读取该参数代码:<selectid="getMaxDepartId"parameterType="java.lang.String"resultType="java.lang.String">SELECTMAX(DEPART_ID......
  • mybatis中大于等于小于等于的写法
    第一种写法(1):原符号<<=>>=&'"替换符号<<=>>=&amp;&apos;"例如:sql如下:create_date_time>=#{startTime}andcreate_date_time<=#{endTime} 第二种写法......
  • 【Vue项目实践】套用github 上的项目(vue3 + Element Plus)运行 可编辑表格
    在Vue3+ElementPlus中生成动态表格gitclonehttps://github.com/kalacloudCode/how-to-build-dynamic-table-in-vue-element-plus.git参考博客:vue3+ElementPlus......
  • 【Vue项目实践】(vue3 + Element Plus)excel 导出
    安装依赖yarnadd--savexlsxfile-saver1、添加导出按钮以及点击事件<el-buttontype="primary"round@click="exportClick">导出表格</el-button>2、在table表格中添加......