在Mybatis框架上做增强的工具
在原有的mybatis中导入mybatisplus坐标
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
连接池坐标
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
主要的修改在dao层
以前的mybatis需要写数据库操作语句,现在就只要继承一个BaseMapper
@Mapper
public interface UserDao extends BaseMapper<User> {
}
mybatisplus主要做单表CRUD,多表的CRUD还是需要自己写
Lombok
一款插件,可以快速构建实体类的构造方法
导入坐标
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
还需要安装Lombok插件
@Data
public class User {
private Long id;
private String name;
private String password;
private Integer age;
private String tel;
}
查询所有
@SpringBootTest
class MybatisplusLombokDemoApplicationTests {
@Autowired
private UserDao userDao;
@Test
void selectAll(){
userDao.selectList(null);
//使用查询list,参数设置为null
}
}
Mybatis分页查询
先定义一个分页拦截器
@Configuration
public class MpConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//创建MybatisPlusInterceptor的拦截器
MybatisPlusInterceptor myInterceptor = new MybatisPlusInterceptor();
//将分页拦截器加入MybatisPlus的拦截器
myInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return myInterceptor;
}
}
执行分页查询
@Test
void page(){
//创建IPage分页对象,参数传递当前页码和需要查询多少条数据
IPage<User> page = new Page<>(1,5);
//执行分页查询
userDao.selectPage(page,null);
System.out.println("每页个数"+page.getSize());
System.out.println("当前页码"+page.getCurrent());
System.out.println("总页数"+page.getPages());
System.out.println("总条数"+page.getTotal());
System.out.println("当前页的数据"+page.getRecords());
}
开启MybatisPlus日志
在yml文件中开启
# 开启mp的日志(输出到控制台)
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
关闭spring日志打印
在resource下创建一个logback.xml文件,文件名固定
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
</configuration>
关闭SpringBoot的启动标志
在yml文件中关闭
spring:
main:
banner-mode: off # 关闭SpringBoot启动图标(banner)
关闭MybatisPlus启动图标
在yml文件中关闭
# mybatis-plus日志控制台输出
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
banner: off # 关闭mybatisplus启动图标
DQL编程控制
三种条件查询的方法
方法一:按条件查询
//QueryWrapper可以用来添加条件
QueryWrapper<User> qw = new QueryWrapper<>();
//查询年龄小于12的数据
qw.lt("age",12);
System.out.println(userDao.selectList(qw));
方法二:lambda格式按条件查询
QueryWrapper<User> qw = new QueryWrapper<>();
//可以添加lambda格式
qw.lambda().gt(User::getAge,12);
System.out.println(userDao.selectList(qw));
方法三:lambda格式按条件查询
//LambdaQueryWrapper可以之间省略后面的.lambda(),直接使用lambda格式
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
lqw.lt(User::getAge,12);
System.out.println(userDao.selectList(lqw));
条件组合
//并且关系(and)
lqw.gt(User::getAge,12).lt(User::getAge,30);
//或者关系(or)
lqw.lt(User::getAge,12).or().gt(User::getAge,30);
对null值的处理
方法的第一个参数可以传递一个boolean值,用来控制条件是否使用,如果为true则使用,false则不使用
Integer minAge=10;
Integer maxAge=null;
lqw.gt(minAge!=null,User::getAge, minAge);
lqw.lt(maxAge!=null,User::getAge, maxAge);
commons-lang包可以对字符串进行操作
导入坐标
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
StringUtils.isNotBlank(name)//用来判断字符串不为空也不为空字符串
映射投影
/*lqw.select(User::getId, User::getName, User::getAge);*/
//或者
QueryWrapper<User> lqw = new QueryWrapper<User>();
lqw.select("id", "name", "age", "tel");
//只查询这几个字段的数据
QueryWrapper<User> lqw = new QueryWrapper<User>();
//查询个数,和tel的数据
lqw.select("count(*) as count, tel");
//通过tel分组
lqw.groupBy("tel");
//通过键值对的形式展示
List<Map<String, Object>> userList = userDao.selectMaps(lqw);
System.out.println(userList);
条件查询
between,查询范围内的数据
//第一个参数是对应的列,第二个是大于的参数,第三个是小于的参数
//(10<User::getAge<30)
lqw.between(User::getAge, 10, 30);
List<User> userList = userDao.selectList(lqw);
模糊查询
lqw.like(Student::getName,"德"); -> // %德%
lqw.likeRight(Student::getName,"马"); -> // 马% Riget表示百分号在字段右边
lqw.likeLeft(Student::getName,"马"); -> // %马 Left表示百分号在字段左边
and嵌套
qw.and(i->i.eq("char_length(name)",2).likeRight("name","马"));//姓马并且字符串长度为2
字段映射与表名映射
//当实体类和表列名不对应可以使用@TableField的value设置对应的数据库表中的字段关系
@TableField(value = "pwd")
private String password;
//当属性名在数据库表中不存在,可以使用@TableField的exist进行注释
@TableField(exist = false)
private Integer online;
//开通通过@TableField的select设置该属性是否参与查询
@TableField(value = "pwd",select = false)
private String password;
//当实体类名和数据库表名不对应时可以使用@TableName("表名")进行设置
@TableName("tbl_user")
public class User {
}
id生成策略控制
//@TableId(type = ***)设置id生成的策略
@TableId(type = IdType.AUTO)
private Long id;
IdType.AUTO:使用数据库id自增策略控制id生成
IdType.NONE:不设置id生成策略
IdType.INPUT:用户手动输入id
IdType.ASSIGN_ID:雪花算法生成id(可兼容数字类型和字符串类型)
IdType.ASSIGN_UUID:以UUID算法作为id的生成策略
id生成策略全局配置
mybatis-plus:
global-config:
db-config:
id-type: assign_id #设置id生成策略
table-prefix: tbl_ #设置所有映射表明前加上tbl_ -> tbl_user
多记录操作
userDao.deleteBatchIds(list);//删除集合中所有id数据
userDao.selectBatchIds(list);//查询集合中所有id数据
逻辑删除
为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,数据保留在数据库中
1.数据库中添加逻辑删除对应字段
deleted
2.创建实体类,实体类中添加对应字段,设置当前字段为逻辑删除标记字段
@Data
public class UserLog extends User{//使用继承获取父类的属性,并且添加子类特有属性
//逻辑删除字段,标记当前记录是否被删除
@TableLogic
private Integer deleted;
}
3.在配置中配置逻辑删除字面值
mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
# 逻辑删除字段名
logic-delete-field: deleted
# 逻辑删除字面值:未删除为0
logic-not-delete-value: 0
# 逻辑删除字面值:删除为1
logic-delete-value: 1
乐观锁(不常用)
在我们从数据库获得数据时也会获得一个乐观锁对应的数值,如果当两个用户同时获取到同一个乐观锁数值,当其中一位用户执行完操作,乐观锁的数值就会进行更改,当第二位用户在操作完后发现乐观锁的数值不对应,那么第二个用户的操作就会失败
只有当操作完成,乐观锁的数据才会更改
1.在数据库表中添加乐观锁对应字段
version
2.创建实体类,实体类中添加对应字段,设置当前字段为乐观锁标记字段
@Data
public class User extends User{
//标记当前字段为乐观锁
@Version
private Integer version;
}
3.在MybatisPlus拦截器中加入乐观锁拦截器
@Configuration
public class MpConfig {
@Bean
public MybatisPlusInterceptor mpInterceptor() {
//1.定义Mp拦截器
MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
//2.添加乐观锁拦截器
mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mpInterceptor;
}
}
4.使用乐观锁我们需要先查询对应的所有数据
User user = userDao.selectById(3L); //version=3
User user2 = userDao.selectById(3L);//version=3
user2.setName("Jock aaa");
userDao.updateById(user2); //version=>4
user.setName("Jock bbb");
userDao.updateById(user);//verion=3?条件还成立吗?