MyBatisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率
DQL编程控制
// 创建 LambdaQueryWrapper 对象,用于构建查询条件LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();// 1. 等值查询// 添加等于条件,查询 username 等于 "john_doe" 的记录lqw.eq(User::getUsername, "john_doe");// 2. 不等值查询// 添加不等于条件,查询 age 不等于 25 的记录lqw.ne(User::getAge, 25);// 3. 大于查询// 添加大于条件,查询 age 大于 18 的记录lqw.gt(User::getAge, 18);// 4. 大于等于查询// 添加大于等于条件,查询 age 大于等于 18 的记录lqw.ge(User::getAge, 18);// 5. 小于查询// 添加小于条件,查询 age 小于 30 的记录lqw.lt(User::getAge, 30);// 6. 小于等于查询// 添加小于等于条件,查询 age 小于等于 30 的记录lqw.le(User::getAge, 30);// 7. 模糊查询// 添加模糊查询条件,查询 username 包含 "doe" 的记录lqw.like(User::getUsername, "doe");// 8. 范围查询// 添加范围查询条件,查询 age 在 20 到 30 之间的记录lqw.between(User::getAge, 20, 30);// 9. 排序查询 - 升序// 按 age 字段升序排序lqw.orderByAsc(User::getAge);// 10. 排序查询 - 降序// 按 age 字段降序排序lqw.orderByDesc(User::getAge);// 11. 分组查询// 按 gender 字段分组lqw.groupBy(User::getGender);// 12. 逻辑与查询// 添加逻辑与条件,查询 age 等于 25 且 gender 等于 "male" 的记录lqw.and(wrapper -> wrapper.eq(User::getAge, 25).eq(User::getGender, "male"));// 13. 逻辑或查询// 添加逻辑或条件,查询 age 等于 25 或 age 等于 30 的记录lqw.or(wrapper -> wrapper.eq(User::getAge, 25).eq(User::getAge, 30));// 14. 查询指定字段// 只查询 username 和 age 字段lqw.select(User::getUsername, User::getAge);
聚合查询
需求:聚合函数查询,完成count、max、min、avg、sum的使用
count:总记录数
max:最大值
min:最小值
avg:平均值
sum:求和
@SpringBootTest
class Mybatisplus02DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testGetAll(){QueryWrapper<User> lqw = new QueryWrapper<User>();//lqw.select("count(*) as count");//SELECT count(*) as count FROM user//lqw.select("max(age) as maxAge");//SELECT max(age) as maxAge FROM user//lqw.select("min(age) as minAge");//SELECT min(age) as minAge FROM user//lqw.select("sum(age) as sumAge");//SELECT sum(age) as sumAge FROM userlqw.select("avg(age) as avgAge");//SELECT avg(age) as avgAge FROM userList<Map<String, Object>> userList = userDao.selectMaps(lqw);System.out.println(userList);}
}
排序查询
/*** condition :条件,返回boolean,当condition为true,进行排序,如果为false,则不排序* isAsc:是否为升序,true为升序,false为降序* columns:需要操作的列*/
映射匹配兼容性
知识点1:@TableField
名称 | @TableField |
---|---|
类型 | 属性注解 |
位置 | 模型类属性定义上方 |
作用 | 设置当前属性对应的数据库表中的字段关系 |
相关属性 | value(默认):设置数据库表字段名称 exist:设置属性在数据库表字段中是否存在,默认为true,此属性不能与value合并使用 select:设置属性是否参与查询,此属性与select()映射配置不冲突 |
知识点2:@TableName
名称 | @TableName |
---|---|
类型 | 类注解 |
位置 | 模型类定义上方 |
作用 | 设置当前类对应于数据库表关系 |
相关属性 | value(默认):设置数据库表名称 |
用于解决表的名称和模型类的名称不一致
id生成策略控制
知识点1:@TableId
名称 | @TableId |
---|---|
类型 | 属性注解 |
位置 | 模型类中用于表示主键的属性定义上方 |
作用 | 设置当前类中主键属性的生成策略 |
相关属性 | value(默认):设置数据库表主键名称 type:设置主键属性的生成策略,值查照IdType的枚举值 |
从源码中可以看到,除了AUTO这个策略以外,还有如下几种生成策略:
- NONE: 不设置id生成策略
- INPUT:用户手工输入id
- ASSIGN_ID:雪花算法生成id(可兼容数值型与字符串型)
- ASSIGN_UUID:以UUID生成算法作为id生成策略
- 其他的几个策略均已过时,都将被ASSIGN_ID和ASSIGN_UUID代替掉。
雪花算法
ID生成策略对比
- NONE: 不设置id生成策略,MP不自动生成,约等于INPUT,所以这两种方式都需要用户手动设置,但是手动设置第一个问题是容易出现相同的ID造成主键冲突,为了保证主键不冲突就需要做很多判定,实现起来比较复杂
- AUTO:数据库ID自增,这种策略适合在数据库服务器只有1台的情况下使用,不可作为分布式ID使用
- ASSIGN_UUID:可以在分布式的情况下使用,而且能够保证唯一,但是生成的主键是32位的字符串,长度过长占用空间而且还不能排序,查询性能也慢
- ASSIGN_ID:可以在分布式的情况下使用,生成的是Long类型的数字,可以排序性能也高,但是生成的策略和服务器时间有关,如果修改了系统时间就有可能导致出现重复主键
- 综上所述,每一种主键策略都有自己的优缺点,根据自己项目业务的实际情况来选择使用才是最明智的选择。
逻辑删除的本质为:
逻辑删除的本质其实是修改操作。如果加了逻辑删除字段,查询数据时也会自动带上逻辑删除字段。
@TableLogic
名称 | @TableLogic |
---|---|
类型 | 属性注解 |
位置 | 模型类中用于表示删除字段的属性定义上方 |
作用 | 标识该字段为进行逻辑删除的字段 |
相关属性 | value:逻辑未删除值 delval:逻辑删除值 |
乐观锁
数据库和java添加version属性
@Configuration
@MapperScan("com.yourpackage.mapper")
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}
快速开发
代码生成器
package com.stdu;import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.model.ClassAnnotationAttributes;
import lombok.Data;import java.sql.Types;
import java.util.Collections;public class CodeGenerator {public static void main(String[] args) {String database = "jdbc:mysql://localhost:3306/lxy?useSSL=false";String table = "51_job";String tablePrefix = "51_";String path = "D:\\Idea项目\\echarts-demo\\echarts_1_test\\src\\main";//取到当前java文件的绝对路径FastAutoGenerator.create(database, "root", "123456").globalConfig(builder -> {builder.author("XYu1230") // 设置作者.enableSwagger() // 开启 swagger 模式.outputDir(path + "\\java") // 指定输出目录.disableOpenDir();}).dataSourceConfig(builder ->builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {int typeCode = metaInfo.getJdbcType().TYPE_CODE;if (typeCode == Types.SMALLINT) {// 自定义类型转换return DbColumnType.INTEGER;}return typeRegistry.getColumnType(metaInfo);})).packageConfig(builder ->builder.parent("com.stdu") // 设置父包名
// .moduleName("system") // 设置父包模块名.pathInfo(Collections.singletonMap(OutputFile.xml, path + "\\resources\\com\\stdu\\mapper")) // 设置mapperXml生成路径).strategyConfig(builder ->builder.addInclude(table) // 设置需要生成的表名.addTablePrefix(tablePrefix) // 设置过滤表前缀.entityBuilder().enableFileOverride().enableLombok(new ClassAnnotationAttributes("@Data","lombok.Data")).controllerBuilder().enableRestStyle())
// .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板.execute();}
}