官网地址: MybatisPlus
- 无侵入:只做增强不做改变,不会对现有工程产生影响
- 强大的 CRUD 操作:内置通用 Mapper,少量配置即可实现单表CRUD操作
- 支持Lambda:编写查询条件无需担心字段写错
- 支持主键自动生成
- 内置分页插件
依赖导入
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
application.yaml配置
server:
port: 8080 # 端口号
spring:
application:
name: reggie-web-manage # 应用名称
datasource: # 数据源配置
druid:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/reggie?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: root
#mybatis:
# configuration:
# map-underscore-to-camel-case: true # 驼峰命名法映射 address_book ---> AddressBook
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 日志输出
# mapper-locations: classpath:/mappers/**.xml # 指定xml位置
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:/mappers/**.xml
global-config:
db-config:
id-type: ASSIGN_ID # id生成策略类型 雪花算法(建议)
实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("user")//当前实体类对应的数据表名,默认值为当前类名首字母小写
public class User {
/**
* Mybatis支持的主键生成策略
* AUTO 数据库ID自增 尽量不要去用
* INPUT 用户输入ID
* ASSIGN_ID 雪花算法生成ID 生成的是数字
* ASSIGN_UUID UUID算法生成ID 生成的是字符串
*/
@TableField("id")//当前属性对应的数据表字段,默认值为当前属性名
@TableId(type = IdType.ASSIGN_ID)//用于标识主键字段, type用于指定主键生成策略
private Long id;
@TableField("name") //指定当前属性对应表中的字段名;如果省略注解,默认字段名为当前属性名
private String name;
@TableField(select = false)//标识不想将数据表中某个对应字段查询回来
private String password;
@TableField(exist = false)//标识当前属性在数据表中没有对应的字段 默认为true
private String password2;
//逻辑删除字段,标记当前记录是否被删除
//value用于指定未删除状态的值, delval用于指定删除状态的值
@TableLogic(value = "0", delval = "1")
private Integer deleted;
private Integer age;
private String tel;
// 自动填充
@TableField(fill = FieldFill.INSERT) // 需要编写自动填充逻辑才生效
private Date createTime;//创建时间
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;//更新时间
}
在
reggie-mapper
模块下创建com.itheima.reggie.config.MyMetaObjectHandler
类,内容如下
package com.itheima.reggie.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
// 自定义元数据对象处理器
// 自动填充逻辑
@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入操作,自动填充
@Override
public void insertFill(MetaObject metaObject) {
metaObject.setValue("createTime", new Date());
metaObject.setValue("updateTime", new Date());
metaObject.setValue("createUser", 1L);
metaObject.setValue("updateUser", 1L);
}
//更新操作,自动填充
@Override
public void updateFill(MetaObject metaObject) {
metaObject.setValue("updateTime", new Date());
metaObject.setValue("updateUser", 1L);
}
}
分页配置
在
reggie-mapper
模块下创建com.itheima.reggie.config.MybatisPlusConfig
类,内容如下
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 分页配置器
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//1 创建MybatisPlusInterceptor拦截器对象
MybatisPlusInterceptor mpInterceptor=new MybatisPlusInterceptor();
//2 添加分页拦截器
mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mpInterceptor;
}
}
分页使用
//分页查询
@Test
public void test4() {
//1. 设置分页条件 pageNum pageSize
Page<User> page = new Page<User>(pageNum, pageSize);
//2. 设置业务条件
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(User::getId,1); // where id > 1
//3. 执行查询
page = userMapper.selectPage(page, wrapper);
System.out.println("总条数:" + page.getTotal());
System.out.println("总页数:" + page.getPages());
System.out.println("当前页数据:" + page.getRecords());
System.out.println("当前页码值:" + page.getCurrent());
System.out.println("每页显示数:" + page.getSize());
}
查询条件
查询方法 | 说明 | 例子 |
---|---|---|
eq、ne、gt、ge、lt、le、isNull、isNotNull | 比较运算 | eq(“name”, “老王”)---> name = ‘老王’ gt: > ge: >= |
like、notLike、likeLeft、likeRight | 模糊查询 | likeRight(“name”, “王”)---> name like ‘王%’ |
in、notIn、between、notBetween | 范围运算 | in(“age”,{1,2,3})---> age in (1,2,3) |
or、and | 拼接 | eq(“id”,1).or().eq(“name”,“老王”)---> id = 1 or name = ‘老王’ |
Lambda用法
//根据age查询 (age>10) lambda
@Test
public void testSelectList3() {
Integer age = 10;//查询条件
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
//参数1:条件,只有这个条件成立,当前这行代码才生效
//参数2:固定写法,指的是类的属性名
//参数3:值
wrapper.gt(age != null, User::getAge, age);
List<User> userList = userMapper.selectList(wrapper);
System.out.println(userList);
}
投影、排序、分组、过滤
查询投影主要用于控制返回哪些列的数据
查询方法 | 说明 | 例子 |
---|---|---|
orderByAsc、orderByDesc | 排序 | orderByDesc(“id”, “name”)---> order by id DESC,name DESC |
groupBy | 分组 | groupBy(“id”, “name”)---> group by id,name |
having | 过滤 | having(“sum(age) > 10”)---> having sum(age) > 10 |
//查询返回指定字段(映射 排序)
//select name,age from user order by age asc
@Test
public void test1() {
//1. 封装wrapper
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.select(User::getName, User::getAge);//查询字段对应的属性名
wrapper.orderByAsc(User::getAge);//排序
//2. 执行查询
userMapper.selectList(wrapper);
}
//分组统计 是不能使用LambdaQueryWrapper
//select name,count(*) as count from user group by name having count > 1
@Test
public void test2() {
//1. 封装wrapper
QueryWrapper<User> wrapper = new QueryWrapper<User>();
wrapper.select("name,count(*) as count");
wrapper.groupBy("name");
wrapper.having("count > 1");
//2. 执行查询
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
System.out.println(maps);
}
//针对于统计 过滤 建议自定义方法, 即自己写sql
@Test
public void test3() {
List<Map<String, Object>> maps = userMapper.count1();
System.out.println(maps);
}
注意: 更新要使用UpdateWrapper<User> wrapper = new UpdateWrapper<User>();
的条件构造器