一、MyBatisPlus入门
1.1 简介
MyBatisPlus是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率。
官网:http://mybatis.plus/ 和 https://mp.baomidou.com/
MyBatisPlus的特性:
1.2 入门案例
二、标准数据层开发
2.1 标准数据层CRUD功能
MyBatisPlus提供标准的CRUD方法:
2.2 Lombok
2.3 分页功能(添加拦截器)
MyBatisPlus提供了分页查询功能,但是需要设置分页查询的拦截器的配置。
2.4 mybaitsplus的日志
此外,为了能够看到查询结果和sql语句,可以在application.yml开启mybaitsplus的日志
三、条件查询
3.1 条件查询的三种方式 和 组合查询条件(and or)
//方式一:按条件查询
System.out.println("\n\n");
System.out.println("-----------方式一:按条件查询---------------");
QueryWrapper qw1 = new QueryWrapper();
qw1.lt("age",18);
List<User> userList1 = userDao.selectList(qw1);
System.out.println(userList1);
//方式二:lambda格式按条件查询
System.out.println("\n\n");
System.out.println("-----------方式二:lambda格式按条件查询---------------");
QueryWrapper<User> qw2 = new QueryWrapper<User>();
// 这里将string形式改成lambda形式
qw2.lambda().lt(User::getAge, 10);
List<User> userList2 = userDao.selectList(qw2);
System.out.println(userList2);
//方式三:lambda格式按条件查询
System.out.println("\n\n");
System.out.println("-----------方式三:lambda格式按条件查询---------------");
LambdaQueryWrapper<User> lqw3 = new LambdaQueryWrapper<User>();
lqw3.lt(User::getAge, 10);
List<User> userList3 = userDao.selectList(lqw3);
System.out.println(userList3);
//并且与或者关系
System.out.println("\n\n");
System.out.println("-----------并且与或者关系---------------");
LambdaQueryWrapper<User> lqw4 = new LambdaQueryWrapper<User>();
//并且关系:10到30岁之间
//lqw.lt(User::getAge, 30).gt(User::getAge, 10);
//或者关系:小于10岁或者大于30岁
lqw4.lt(User::getAge, 10).or().gt(User::getAge, 30);
List<User> userList4 = userDao.selectList(lqw4);
System.out.println(userList4);
3.2 空值处理(null)
传统空值处理,需要写很多判断条件;mp直接将空值处理放在方法的第一个参数上,当其为true时,才执行后面的参数代码。
// 空值处理
System.out.println("\n\n");
System.out.println("-----------空值处理---------------");
// 1)模拟页面传递过来的查询数据,保证数据的age在10~30之间
UserQuery uq = new UserQuery();
uq.setAge(10);
uq.setAge2(30);
// 2)传统:null判定
LambdaQueryWrapper<User> lqw6 = new LambdaQueryWrapper<User>();
if( null != uq.getAge2()) {
lqw6.lt(User::getAge, uq.getAge2());
}
if( null != uq.getAge()) {
lqw6.gt(User::getAge, uq.getAge());
}
List<User> userList6 = userDao.selectList(lqw6);
System.out.println(userList6);
// 3)mp的空值处理
LambdaQueryWrapper<User> lqw5 = new LambdaQueryWrapper<User>();
//先判定第一个参数是否为true,如果为true连接当前条件
// lqw5.lt(null != uq.getAge2(),User::getAge, uq.getAge2());
// lqw5.gt(null != uq.getAge(),User::getAge, uq.getAge());
lqw5.lt(null != uq.getAge2(),User::getAge, uq.getAge2())
.gt(null != uq.getAge(),User::getAge, uq.getAge());
List<User> userList5 = userDao.selectList(lqw5);
System.out.println(userList5);
3.3 查询投影(只看某些字段/列,count,group by)
//查询投影
System.out.println("\n\n");
System.out.println("-----------查询投影---------------");
// LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
// lqw.select(User::getId,User::getName,User::getAge);
QueryWrapper<User> lqw7 = new QueryWrapper<User>();
lqw7.select("id","name","age","tel");
List<User> userList7 = userDao.selectList(lqw7);
System.out.println(userList7);
QueryWrapper<User> lqw8 = new QueryWrapper<User>();
lqw8.select("count(*) as count, tel");
lqw8.groupBy("tel");
// 注意:这里是selectMaps
List<Map<String, Object>> userList8 = userDao.selectMaps(lqw8);
System.out.println(userList8);
3.4 查询条件
//条件查询
System.out.println("\n\n");
System.out.println("-----------条件查询---------------");
LambdaQueryWrapper<User> lqw9 = new LambdaQueryWrapper<User>();
//1) eq等同于=
lqw9.eq(User::getName,"zhansan").eq(User::getPassword,"123456");
User loginUser9 = userDao.selectOne(lqw9);
System.out.println(loginUser9);
LambdaQueryWrapper<User> lqw10 = new LambdaQueryWrapper<User>();
//2) 范围查询 lt表示< le表示<= gt表示> ge表示>= eq表示= between表示>=并且<
lqw10.between(User::getAge,10,30);
List<User> userList10 = userDao.selectList(lqw10);
System.out.println(userList10);
LambdaQueryWrapper<User> lqw11 = new LambdaQueryWrapper<User>();
//3) 模糊匹配 likeLeft 表示 %z , likeRight 表示 z%
lqw11.likeRight(User::getName,"z");
List<User> userList11 = userDao.selectList(lqw11);
System.out.println(userList11);
3.5、字段映射与表名映射
@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 String online;
}
四、DML编程控制-增删改
4.1 Id生成策略(Insert)
4.2 多数据操作(Delete、Insert)
4.3 逻辑删除(Delete\Update)
第一步:数据库表中添加逻辑删除的标记字段,并设置默认值为0
第二步:在实体类中添加相应字段
@Data
//@TableName("tbl_user")
public class User {
// @TableId(type = IdType.INPUT)
private Long id;
private String name;
@TableField(value = "pwd",select = false)
private String password;
private Integer age;
private String tel;
@TableField(exist = false)
private String online;
// 逻辑删除字段,标记当前记录是否被删除
// 默认值为0,当为1时表明该数据已经删除
// 当执行删除语句时,自动将该字段值设置为1;当执行查询语句时,自动排除 属性值=1 的数据
@TableLogic(value = "0" ,delval = "1")
private Integer deleted;
// @Version
// private Integer version;
}
第三步:测试
@Test
void testDelete(){
userDao.deleteById(2L);
System.out.println(userDao.selectList(null));
}
第四步:在删除操作语句自动执行update操作,并且where值与你设定的一样;查询语句也自动添加了where判断
4.4 乐观锁(Update)(添加拦截器)
记得加上默认值
@Test
void testUpdate(){
//1.先通过要修改的数据id将当前数据查询出来
User user = userDao.selectById(1L); //version=3
User user2 = userDao.selectById(1L); //version=3
user2.setName("Jock aaa");
userDao.updateById(user2); //version->4
user.setName("Jock bbb");
userDao.updateById(user); //此时user拿到的verion=3,而version已经变成了4,条件不成立,无法修改,因此,加锁成功
}
五、全局配置
上述,@TableName、@TableId、@TableLogic等可以用application.yml里面全局配置替换。
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
# 关闭Spring的banner
main:
banner-mode: off
# mybatisplus 日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 关闭mybatis的banner
global-config:
banner: false
# 全局配置 -- id自增策略、表名、逻辑删除(3行)
db-config:
id-type: assign_id
table-prefix: tbl_
logic-delete-field: deleted
logic-delete-value: 1
logic-not-delete-value: 0
六、快速开发—代码生成器
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();
}
}