文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

MyBatis-Plus 条件查询器的实现

2024-04-02 19:55

关注

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

一、常用注解

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

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

所以我们的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: t_

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

1.2 @TableId

MyBatis-Plus在实现CRUD时,会默认将id作为主键列,并在插入数据时,默认是基于雪花算法的策略生成idASSIGN_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 {
    
    AUTO(0),
    
    NONE(1),
    
    INPUT(2),

    
    
    ASSIGN_ID(3),
    
    ASSIGN_UUID(4);

    private final int key;

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

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

1.3 @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)则在查询的时候就不会显示查询出来的值

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;

}

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

测试删除功能,真正执行的是修改

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

【继承关系】

Wrapper : 条件构造抽象类,最顶端父类

这里主要就是介绍QueryWrapper和UpdateWrapper

2.1 QueryWrapper

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

2.1.1 组装查询条件selectCount


	@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


	@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


	@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


	@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("modifyTest@gogel.com");
		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;
	}

2.2 UpdateWrapper

2.2.1 组装修改条件update

@Test
	public void testUpdate2() throws Exception {
		User user = new User();
		user.setEmail("modifyTest@gogel.com");
		UpdateWrapper<User> updateWrapper = new UpdateWrapper<User>();
		updateWrapper.ge("age", 20).like("user_name", "a").or().isNull("email");
		
		int row = userMapper.update(user, updateWrapper);

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

三、MyBatis-Plus分页插件

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

3.1 实现步骤

1️⃣添加配置类


@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的通用枚举来实现

4.1 数据库表添加字段sex

4.2 配置扫描通用枚举

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

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(以前的库不动)与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 条件查询器的实现的文章就介绍到这了,更多相关MyBatis-Plus 条件查询器内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯