目录
简介
MybatisPlus(
简称
MP)
是基于
MyBatis
框架基础上开发的增强型工具,旨在简化开发、提供效
率,官网为https://mp.baomidou.com/
,特性有很多:
- 无侵入:只做增强不做改变,不会对现有工程产生影响
- 强大的 CRUD 操作:内置通用 Mapper,少量配置即可实现单表CRUD 操作
- 支持 Lambda:编写查询条件无需担心字段写错
- 支持主键自动生成
- 内置分页插件
- ……
标准CRUD使用
MybatisPlus提供了内置的方法使用,具体可以看DAO接口继承的BaseMapper类
- 新增
//int:返回值,新增成功后返回1,没有新增成功返回的是0 int insert (T t)
- 删除
//int:返回值类型,数据删除成功返回1,未删除数据返回0 int deleteById (Serializable id)
- 修改
//修改的时候,只修改实体对象中有值的字段 int updateById(T t);
- 根据id查询
//Serializable:参数类型,主键ID的值 T selectById (Serializable id)
- 查询所有
//Wrapper:用来构建条件查询的条件,目前我们没有可直接传为Null List<T> selectList(Wrapper<T> queryWrapper)
- Lombok,一个Java类库,提供了一组注解,简化POJO实体类开发,常见注解如下:
@Setter: 为模型类的属性提供 setter 方法@Getter: 为模型类的属性提供 getter 方法@ToString: 为模型类的属性提供 toString 方法@EqualsAndHashCode: 为模型类的属性提供 equals 和 hashcode 方法@Data: 是个组合注解,包含上面的注解的功能@NoArgsConstructor: 提供一个无参构造函数@AllArgsConstructor: 提供一个包含所有参数的构造函数
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <!--<version>1.18.12</version>--> </dependency>
- 分页查询(需要配合分页拦截器使用),IPage是一个接口,我们需要找到它的实现类来构建它,具体的实现类,可以进入到IPage类中按ctrl+h,会找到其有一个实现类为Page。
//IPage用来构建分页查询条件,Wrapper用来构建条件查询的条件 IPage<T> selectPage(IPage<T> page, Wrapper<T> queryWrapper)
//可参考官网文档 @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ //1 创建MybatisPlusInterceptor拦截器对象 MybatisPlusInterceptor mpInterceptor=new MybatisPlusInterceptor(); //2 添加分页拦截器 mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return mpInterceptor; } }
DQL编程控制
MyBatisPlus
将书写复杂的
SQL
查询条件进行了封装,使用编程的形式完成查询条件的组合
条件查询
在进行查询的时候,我们的入口是在
Wrapper这个类上,因为它是一个接口,所以我们需要去找它对应的实现类,关于实现类也有很多,说明我们有多种构建查询条件对象的方式
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(User::getAge, 10).or().gt(User::getAge, 30);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
相当于
SELECT id,name,password,age,tel FROM user WHERE (age < ? OR age > ?)
条件null判定
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(null!=uq.getAge2(),User::getAge, uq.getAge2());
lqw.gt(null!=uq.getAge(),User::getAge, uq.getAge());
List<User> userList = userDao.selectList(lqw);
//condition为boolean类型,返回true,则添加条件,返回false则不添加条件
查询投影
查询指定字段
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.select(User::getId,User::getName,User::getAge);
List<User> userList = userDao.selectList(lqw);
或
QueryWrapper<User> lqw = new QueryWrapper<User>();
lqw.select("id","name","age","tel");
List<User> userList = userDao.selectList(lqw);
查询条件
查询条件有很多,包括>,=,<,like,null,in,group,order
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.eq(User::getName, "Jerry").eq(User::getPassword, "jerry");//等值查询
lqw.between(User::getAge, 10, 30);//范围查询
lqw.likeLeft(User::getName, "J");//模糊查询%J
lqw.like(User::getName, "J");//模糊查询%J%
lqw.likeRight(User::getName, "J");//模糊查询J%
lqw.orderBy(true,false, User::getId);//是否排序:是,是否升序:否,排序字段
User loginUser = userDao.selectOne(lqw);
映射匹配兼容性
问题:属性名与表名不一致?模型类中多了一个数据库表不存在的字段?敏感数据不想被查出来?表的名称和模型类的名称不一致?如下注解一一解决
@Data
@TableName("tbl_user")
public class User {
private Long id;
private String name;
@TableField(value = "pwd",select = false)
private String password;
private Integer age;
private String tel;
@TableField(exist = false)
private Integer online;
}
DML编程控制
ID生成策略
不同的业务采用的
ID生成方式是不一样的,其中auto是使用数据库ID自增,input需要手动设置id,assign_id不需要手动设置id,会根据雪花算法自动生成
一个64位
Long类型的数据;assign_uuid则自动生成
一个32位
String
类型的数据
@Data
@TableName("tbl_user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
}
- NONE: 不设置id生成策略,MP不自动生成,约等于INPUT,所以这两种方式都需要用户手动设置,但是手动设置第一个问题是容易出现相同的ID造成主键冲突,为了保证主键不冲突就需要做很多判定,实现起来比较复杂
- AUTO:数据库ID自增,这种策略适合在数据库服务器只有1台的情况下使用,不可作为分布式ID使用
- ASSIGN_UUID:可以在分布式的情况下使用,而且能够保证唯一,但是生成的主键是32位的字符 串,长度过长占用空间而且还不能排序,查询性能也慢
- ASSIGN_ID:可以在分布式的情况下使用,生成的是Long类型的数字,可以排序性能也高,但是生成的策略和服务器时间有关,如果修改了系统时间就有可能导致出现重复主键
综上所述,每一种主键策略都有自己的优缺点,根据自己项目业务的实际情况来选择使用才是最明
智的选择。
//让所有的模型类都可以使用该主键ID策略
mybatis-plus:
global-config:
db-config:
id-type: assign_id
//设置所有属性名加上前缀,构成表名
mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
多记录操作
//根据id批量删除
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends
Serializable> idList);
//根据id集合批量查询
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends
Serializable> idList);
相当于select * from tb where id in(?,?,?)
逻辑删除
逻辑删除
:
为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,数据保留在数据库
中,执行的是update操作,相当于
UPDATE tbl_user SET deleted =1 where id = ? AND deleted =0
方式一:模型类的属性上添加@TableLogic注解
@TableLogic(value="0",delval="1")
//value为正常数据的值,delval为删除数据的值
private Integer deleted;
方式二:在配置文件中添加全局配置
mybatis-plus:
global-config:
db-config:
# 逻辑删除字段名
logic-delete-field: deleted
# 逻辑删除字面值:未删除为0
logic-not-delete-value: 0
# 逻辑删除字面值:删除为1
logic-delete-value: 1
乐观锁
官方文档https://mp.baomidou.com/guide/interceptor-optimisticlocker.html#optimisticlockerinnerinterceptor
原理:更新前分别先查询version的值,更新的时候同步将version+1更新回到数据库表中
@Configuration
public class MpConfig {
@Bean
public MybatisPlusInterceptor mpInterceptor() {
//1.定义Mp拦截器
MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
//2.添加乐观锁拦截器
mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mpInterceptor;
}
}
代码生成器
代码自动生成,需导入依赖mybatis-plus-generator及以下内容
- 模板: MyBatisPlus提供,可以自己提供,但是麻烦,不建议
- 数据库相关配置:读取数据库获取表和字段信息
- 开发者自定义配置:手工配置,比如ID生成策略
代码生成类可以参考官方文档https://mp.baomidou.com/guide/generator.html
运行成功后,会在当前项目中生成很多代码,代码包含
controller
,
service
,
mapper
和
entity
package com.itheima;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
public class CodeGenerator {
public static void main(String[] args) {
//1.获取代码生成器的对象
AutoGenerator autoGenerator = new AutoGenerator();
//设置数据库相关配置
DataSourceConfig dataSource = new DataSourceConfig();
dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC");
dataSource.setUsername("root");
dataSource.setPassword("root");
autoGenerator.setDataSource(dataSource);
//设置全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir(System.getProperty("user.dir")+"/mybatisplus_04_generator/src/main/java"); //设置代码生成位置
globalConfig.setOpen(false); //设置生成完毕后是否打开生成代码所在的目录
globalConfig.setAuthor("黑马程序员"); //设置作者
globalConfig.setFileOverride(true); //设置是否覆盖原始生成的文件
globalConfig.setMapperName("%sDao"); //设置数据层接口名,%s为占位符,指代模块名称
globalConfig.setIdType(IdType.ASSIGN_ID); //设置Id生成策略
autoGenerator.setGlobalConfig(globalConfig);
//设置包名相关配置
PackageConfig packageInfo = new PackageConfig();
packageInfo.setParent("com.aaa"); //设置生成的包名,与代码所在位置不冲突,二者叠加组成完整路径
packageInfo.setEntity("domain"); //设置实体类包名
packageInfo.setMapper("dao"); //设置数据层包名
autoGenerator.setPackageInfo(packageInfo);
//策略设置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setInclude("tbl_user"); //设置当前参与生成的表名,参数为可变参数
strategyConfig.setTablePrefix("tbl_"); //设置数据库表的前缀名称,模块名 = 数据库表名 - 前缀名 例如: User = tbl_user - tbl_
strategyConfig.setRestControllerStyle(true); //设置是否启用Rest风格
strategyConfig.setVersionFieldName("version"); //设置乐观锁字段名
strategyConfig.setLogicDeleteFieldName("deleted"); //设置逻辑删除字段名
strategyConfig.setEntityLombokModel(true); //设置是否启用lombok
autoGenerator.setStrategy(strategyConfig);
//2.执行生成操作
autoGenerator.execute();
}
}