Mybatis-plus -2025/1/27
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 {
@Autowired
private UserDao userDao;
@Test
void 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 user
lqw.select("avg(age) as avgAge");
//SELECT avg(age) as avgAge FROM user
List<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 {
@Bean
public 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();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!