mybatis-plus

mybatis-plus入门案例


  • 我们基于springboot使用MP

  • 1.手动添加MP的起步依赖
  • 2.添加dluid的依赖
    <!--druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.20</version>
        </dependency>

数据层代码

  • domain(注意id是long类型)
package com.itheima.domain;

public class Book {
    private Long id;
    private String name;
    private String type;
    private String description;


    public Book() {
    }

    public Book(Long id, String name, String type, String description) {
        this.id = id;
        this.name = name;
        this.type = type;
        this.description = description;
    }

    /**
     * 获取
     * @return id
     */
    public Long getId() {
        return id;
    }

    /**
     * 设置
     * @param id
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return type
     */
    public String getType() {
        return type;
    }

    /**
     * 设置
     * @param type
     */
    public void setType(String type) {
        this.type = type;
    }

    /**
     * 获取
     * @return description
     */
    public String getDescription() {
        return description;
    }

    /**
     * 设置
     * @param description
     */
    public void setDescription(String description) {
        this.description = description;
    }

    public String toString() {
        return "Book{id = " + id + ", name = " + name + ", type = " + type + ", description = " + description + "}";
    }
}

  • dao接口(只需要继承BaseMapper类,其余什么都不需要写,甚至连方法名都不需要写。啊啊啊啊,太强了)
package com.itheima.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.domain.Book;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface BookDao extends BaseMapper<Book> {
}

  • 测试
package com.itheima;

import com.itheima.dao.BookDao;
import com.itheima.domain.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class QuickstartApplicationTests {
    @Autowired
private BookDao bookDao;
    @Test
    void testSelectAll() {
   
        final List<Book> books = bookDao.selectList(null);//查询所有
        for (Book book : books) {
            System.out.println(book);
        }
    }

}


mybatis-plus简介

标准crud制作

  • insert操作

  • update操作
    提供哪些字段才会修改哪些字段,不提供将不会去修改
    之前我们写的update的sql语句一般是set后面默认所有的字段都修改,如果对象中不传入值的话,将都会修改成null
  • crud完整测试代码
package com.itheima;

import com.itheima.dao.BookDao;
import com.itheima.domain.Book;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class QuickstartApplicationTests {
    @Autowired
private BookDao bookDao;
    @Test
    //添加
    void testInsert(){
        Book book = new Book();
       //id不指定,由他自动增长
        book.setName("王者荣耀");
        book.setType("游戏");
        book.setDescription("有趣的游戏");
        bookDao.insert(book);
    }

//查询全部
    @Test
    void testSelectAll() {

        final List<Book> books = bookDao.selectList(null);//查询所有
        for (Book book : books) {
            System.out.println(book);
        }
    }

    //按id进行查询
    @Test
    void testSelectById(){
        final Book book = bookDao.selectById(11L);
        System.out.println(book);
    }
//删除
    @Test
    void testDelete(){
        bookDao.deleteById(1746355658329825281L);
    }
    //修改
    @Test
    void testUpdate(){
        Book book = new Book();
        book.setId(4L);
        book.setName("王者荣耀");
        //其他没有传入值的属性,将不会修改
       bookDao.updateById(book);
    }
}

domain开发的简化

  • 1.导入lombok的jar包

  • 2.使用注解

package com.itheima.domain;

import lombok.*;

@Getter
@Setter
@ToString
@AllArgsConstructor//全参构造
@NoArgsConstructor//无参构造
@EqualsAndHashCode//equals和hanshCode方法覆盖
public class Book {
    private Long id;
    private String name;
    private String type;
    private String description;



}

  • 简单化

标准分页功能的制作



但是在mybatis-plus中不是叫AOP,而是叫拦截器,拦截查询所有操作并增强他
我们必须保证我们配置的拦截器可以被springboot扫描到,我们可以有下面2种方式

  • 1,@import
  • 配置类
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mpInterceptor() {
        //1.定义MP拦截器
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //2.添加具体的拦截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

  • 2.将配置类用注解定义成配置类,由boot自动扫描

    具体代码
  • 分页拦截器
package com.itheima;

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 mpInterceptor() {
        //1.定义MP拦截器
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //2.添加具体的拦截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

@Test
    //分页查询
    void testSelectPage(){
       IPage page = new Page(1,2);
      bookDao.selectPage(page, null);//执行分页查询

        System.out.println("当前页码值:"+page.getCurrent());
        System.out.println("每页显示数:"+page.getSize());
        System.out.println("一共多少页:"+page.getPages());
        System.out.println("一共多少条数据:"+page.getTotal());
        System.out.println("数据:"+page.getRecords());

    }


那MP具体是使用什么sql语句实现分页的呢?



对于分页:1.设置一个拦截器 2.参数设置在IPage中 3.查询结果还是在IPage中

条件查询的三种格式


  • 方式一
  @Test
    //条件查询
    void testSelect(){
        //方式1:按条件查询
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.lt("id",5);//查询id小于5
        final List list = bookDao.selectList(queryWrapper);
        System.out.println(list);
    }

但是这种方式的列名容易写错

 //方式2:lambda格式按条件查询
        QueryWrapper<Book> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().lt(Book::getId,5);//查询id小于5
        final List list = bookDao.selectList(queryWrapper);
        System.out.println(list);
  • 方式3:对方式2的改进
  //方式3:lambda格式按条件查询
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.lt(Book::getId,5);//查询id小于5
        final List list = bookDao.selectList(queryWrapper);
        System.out.println(list);

使用的话,推荐使用方式3

  • 多条件

    前面我们写的条件都是and关系的,那如果我们是or关系的该怎样写呢

条件查询null判定

  • 问题描述
  • 查询条件的封装
package com.itheima.domain.query;

import lombok.Data;

//封装book表的查询条件
@Data
public class BookQuery {
    /*写出可能出现上限和下限的属性(具备查询条件的属性)*/
    private Long id;//id的上线
    private Long id2;//id的下线
}


解决方案

  • 优化方案(调用另外一个条件方法,将判断也封装到里面了)
 void testSelect(){
        BookQuery bookQuery = new BookQuery();
        bookQuery.setId(5L);
      ///  bookQuery.setId2(2L);
        //方式3:lambda格式按条件查询
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper();

        queryWrapper.lt(null!=bookQuery.getId(),Book::getId,bookQuery.getId());//当条件不为空,添加小于条件
        queryWrapper.gt(null!=bookQuery.getId2(),Book::getId,bookQuery.getId2());//当添加不为空,添加大于条件
        final List list = bookDao.selectList(queryWrapper);
        System.out.println(list);
    }

查询投影

就是研究查询出来的结果有多少字段

  • lambda格式设置
   //1.lambda格式设置投影字段
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper();
          queryWrapper.select(Book::getId,Book::getName); //设置投影字段
        final List list = bookDao.selectList(queryWrapper);
        System.out.println(list);
    }
  • 2.非lambda格式设置

    查询表数据的行数

    分组统计

查询条件设置

  • 条件设置--等于=
 //条件查询
    void testSelect(){
        //1.lambda格式设置投影字段
        LambdaQueryWrapper<Book> queryWrapper = new LambdaQueryWrapper();
       queryWrapper.eq(Book::getId,5).eq(Book::getType,"计算机理论");//满足id=5并且type=计算机理论
      Book book = bookDao.selectOne(queryWrapper);//仅仅查询出一行,使用selectOne
        System.out.println(book);
    }
  • 范围查询


映射匹配兼容性


如果我们重新将实体类的属性名修改一下,这显然工程量巨大

  • MP的解决方案





    1.MP会直接将我们实体类的类名改成小写后当成表名使用
  • 总体演示
package com.itheima.domain;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;

@Data
@TableName("tbl_book")//映射表名
public class Book {
    private Long id;
    private String name;
    @TableField(value = "tp",select = false)//设置该字段不参与查询
    private String type;
    private String description;
//添加一个表中没有的字段
    @TableField(exist = false)//标明该字段表中不存在
    private Integer online;


}

DML编程控制

id 生成策略



当id生成策略为input(即需要自动手动指定id),则我们需要在数据库中不设定id自增,而是手动传入id

我们的mp默认使用雪花算法
如果我们要使用一种id自增策略,我们需要在每个实体类的id字段上都添加上测试,这太麻烦了

  • 在配置文件中配置全局id自增策略(添加操作)
  • 在配置文件中配置类名和表名的全局映射

多数据操作(删除与查询)

  • mp中实现多条数据同时删除
  void testDelete(){
        List<Long>list = new ArrayList<>();
        list.add(1746479432933031937L);
        list.add(1746479492160700417L);
        list.add(1746482543491780609L);
        list.add(1746484259935191041L);
        bookDao.deleteBatchIds(list);//根据id进行批量删除
    }
  • 实现多条数据同时查询(和前面的差不多)

逻辑删除(企业开发中经常用到)


  • 1.给我们的表添加上逻辑删除字段

  • 2.在类中设置逻辑删除字段
  • 3.进行删除操作

    标明逻辑删除后,对查询操作的影响

    总结:当添加逻辑删除字段后,所以的查询操作将自动添加where deleted=0的条件
    配置全局逻辑删除字段

    重要提示:配置全局逻辑删除字段对每个表都自动配置逻辑删除字段,但是如果表中没有添加对应的逻辑删除字段,则该配置对他没有用,也不会报错

乐观锁


本质上就是二值信号量,就是是互斥锁来实现同步。version也就是信号量
具体实现看笔记
使用乐观锁拦截器动态修改version的值

快速开发--代码生成器




  • 添加依赖

    代码生成器支持自己配置模板,这里不去做了解



  • 生成器类的配置

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");

对于代码生成器中的代码内容,我们可以直接从官方文档中获取代码进行修改,
https://mp.baomidou.com/guide/generator.html
步骤5:运行程序
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_ge
nerator/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();
}
}

生成代码我们需要的是:1.导入依赖 2.编写代码生成了类(不需要另外进行配置)

posted @ 2024-01-14 23:15  一往而深,  阅读(7)  评论(0编辑  收藏  举报