SpringBoot基础之花式使用MybatisPlus

3,334 阅读4分钟

这是我参与11月更文挑战的第9天,活动详情查看:2021最后一次更文挑战

前言

Mybatis像汽车,但是加持了MybatisPlus绝对是绝对是加装了氮气的超跑.

在没有使用MybatisPlus之前,在查询单表的时候要不默默的写sql代码,要不用代码生成器生成基础的代码,一旦参数有多种匹配方式,那么要不copy一份重写,要不加一个if条件,还是比较难受的.

但是一旦用了MybatisPlus 那仿佛是另一个世界.

MybatisPlus集成项目请看SpringBoot基础之集成MybatisPlus

前置基础信息

SQL

CREATE TABLE `student` (
 `id` bigint(20) NOT NULL AUTO_INCREMENT,
 `info` varchar(255)  COMMENT 'zouzdc',
  `del_flag` tinyint(1) DEFAULT '0',
 `create_time` datetime,
 `create_by` varchar(255),
 `update_time` datetime ,
 `update_by` varchar(255),
 PRIMARY KEY (`id`)
) ;

Bean

@Data
@NoArgsConstructor
public class Student {
    
    /**
     * id
     */
    @TableId
    private Long id;

    /**
     * 其他信息
     */
    private String info;
    
    /**
     * 是否伪删除  0否 1是
     */
    @TableLogic
    private String delFlag;
    
    /**
     * 创建日期
     */
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    /**
     * 创建人
     */
    @TableField(fill = FieldFill.INSERT)
    private String createBy;

    /**
     * 更新日期
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

    /**
     * 更新人
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updateBy;
}

MyBatisPlus增强配置-字段自动填充

正常来说,createTimecreateBydel_flag和租户等信息在输入插入的时候就需要赋值,而updateTimeupdateBy在数据变动的时候就需要重新赋值,对于这种模式固定的字段,可以使用MyBatisPlus的字段自动填充功能,让程序自动帮助我们做.

需要变动的位置,添加一个配置类,需要在Bean上需要的字段上添加注解

需要填充的字段上加注解@TableField(

例子如上图的Student

@TableField(fill = FieldFill.INSERT) 在新增会自动填充该字段,如果字段有值,则不会覆盖

@TableField(fill = FieldFill.INSERT_UPDATE) 在新增和更新都会自动填充该字段,如果字段有值则会覆盖

@TableField(fill = FieldFill.UPDATE) 在更新会自动填充该字段,如果字段有值则会覆盖

字段自动填充配置类

在配置类中,自定义配置每一个需要自动填充数据的字段的填充规则

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {

        this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
        this.strictInsertFill(metaObject, "createBy", String.class,  getUserBy());
        this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
        this.strictInsertFill(metaObject, "updateBy", String.class,  getUserBy());
        // 另一种方式 通用填充功能
        //this.setFieldValByName("createTime",new Date(),metaObject);

    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
        this.strictInsertFill(metaObject, "updateBy", String.class,  getUserBy());
    }

    private String getUserBy(){
        //获取当前操作人的方法,根据自己业务操作
        return "admin";
    }
}

数据逻辑删除

业务系统中大部分表不会真正的删除,所以需要使用某一个字段,定义是否伪删除. 只有调用MybatisPlus自带的方法且定义了删除字段的才会伪删除,否则会真删除.对于自己写的sql需要自行处理.

此处使用del_flag来定义是否伪删除,0是没有删除1是删除

application.yml

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: delFlag  # 全局逻辑删除的实体字段名
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

Bean类上

/**
 * 是否伪删除  0否 1是
 */
@TableLogic
private String delFlag;

官网介绍自从3.3.0开始,在application.yml中配置了全局后, 可以不用再Bean上的字段配置@TableLogic

单表增删改查使用

controller层使用增删改查

@RestController
@RequestMapping("/student")
public class StudentController {

    @Autowired(required = false)
    public StudentService studentService;

    @GetMapping("getById")
    public R getStudentById( Student student){
        //增
        studentService.save(student);
        //改
        studentService.updateById(student);
        //查
        Student student = studentService.getById(student.getId());
        //删
        studentService.removeById(student.getId());
       //列表 带参数查询
        List<Student> zouzdc = studentService.lambdaQuery().eq(Student::getInfo, "zouzdc").list();
        return R.success();
    }
}

service层使用增删改查

增删改查

@Service
@Slf4j
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

    @Autowired(required = false)
    private StudentMapper studentMapper;


    @Override
    public void savePlus(Student student) {
         //增
        studentMapper.insert(student);
         //改
        studentMapper.updateById(student);
          //查
        baseMapper.selectById(student.getId());
          //删
        baseMapper.deleteById(student.getId());
         //列表 带参数查询
        List<Student> list = this.lambdaQuery().eq(Student::getId, student.getId()).list();
    }
}

Service中自带默认的Mapper对象即baseMapper,等同于这里的studentMapper

单表条件查询示例

lambda语法

查询info等于zouzdc的list

 List<Student> zouzdc = studentService.lambdaQuery().eq(Student::getInfo, "zouzdc").list();

查询info等于zouzdc的一个对象

Student zouzdc = studentService.lambdaQuery().eq(Student::getInfo, "zouzdc").one();
Student zouzdc = studentService.lambdaQuery().eq(Student::getInfo, "zouzdc").last(" limit 1").one();

对于非唯一数据,直接使用one(),可能会出现非一条数据报错,可以使用last()拼接参数获取第一条数据

更新id=1info字段

 studentService.lambdaUpdate().set(Student::getInfo,"zdc").eq(Student::getId,1).update();

删除info是'zouzdc'的数据

studentService.lambdaUpdate().set(Student::getInfo,"zouzdc").remove()

更多的条件构造请参看官方文档条件构造器一节

变种语法 不建议使用
 List<Student> zouzdc1 = studentService.list(new QueryWrapper<Student>().lambda().eq(Student::getInfo, "zouzdc"));
 Student zouzdc2 = studentService.getOne(new LambdaQueryWrapper<Student>().eq(Student::getInfo, "zouzdc"));

分页查询

分页配置类

@Configuration
@MapperScan("zdc.enterprise.mapper.*")
public class MybatisPlusConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置最大单页限制数量,,-1 不受限制
        paginationInterceptor.setLimit(1000);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }
}

lambda模式分页


public  IPage<StudentDto> listPage(StudentDto vo){

return this.lambdaQuery()
        .eq(vo.getInfo() != null, Student::getInfo, vo.getInfo())
        .eq(Student::getDelFlag, "0")
        .page(new Page(vo.getCurrent(), vo.getSize()));
}

混合模式分页

Service层

 public  Page<StudentDto> listPage(StudentDto vo){
 
        Page<Student> page = new Page(vo.getCurrent(), vo.getSize());
        page.addOrder(OrderItem.desc("a.create_time"));

        QueryWrapper<Student> wrapper = new QueryWrapper();
        wrapper.apply(" a.del_flag =0 ");
          wrapper.eq("a.info","zouzdc")
                .le("a.id",10);
        return baseMapper.listPage(page, wrapper);
    }

Mapper层

Page<StudentDto> listPage(@Param("page") Page<Student> page, @Param("ew") QueryWrapper<Student> wrapper);

@Param("ew")是固定的默认的

XML层

<select id="listPage" resultType="zdc.enterprise.dto.StudentDto">
    select * from student a
    ${ew.customSqlSegment}

</select>

这种写法是在service层写sql形式的where条件,然后通过${ew.customSqlSegment}拼接到xml中sql的后面.会自带where

还有更多写法...自己研究吧

作者:ZOUZDC
链接:https://juejin.cn/post/7028963866063306760
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。