您现在的位置是:首页 > 正文

SpringBoot整合MybatisPlus(小白也秒懂)

2024-02-01 00:31:42阅读 2

SpringBoot整合MybatisPlus(小白也秒懂)

话不多说,上流程

创建好对应的数据库和表

-- 删除tb_brand表
drop table if exists tb_brand;
-- 创建tb_brand表
create table tb_brand
(
    -- id 主键
    id           int primary key auto_increment,
    -- 品牌名称
    brand_name   varchar(20),
    -- 企业名称
    company_name varchar(20),
    -- 排序字段
    ordered      int,
    -- 描述信息
    description  varchar(100),
    -- 状态:0:禁用  1:启用
    status       int
);
-- 添加数据
insert into tb_brand (brand_name, company_name, ordered, description, status)
values ('三只松鼠', '三只松鼠股份有限公司', 5, '好吃不上火', 0),
       ('华为', '华为技术有限公司', 100, '华为致力于把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界', 1),
       ('小米', '小米科技有限公司', 50, 'are you ok', 1);

创建SpringBoot项目

目录结构在这里插入图片描述

导入pom.xml配置

   <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.0</version>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 日志依赖-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>
<!--        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>
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
        </dependency>

    </dependencies>

yml文件配置

server:
  port: 8889

spring:
  application:
    name: mybatis_test
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_test?useSSL=false&serverTimezone=UTC
    username: root
    password: 1234
 mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印SQL日志到控制台
  global-config:
    db-config:
      id-type: auto #主键id生成策略。

创建对应的实体类

@Data
@Entity
@TableName("tb_brand")
public class Brand implements Serializable {
    private Integer id;
    // 品牌名称
    private String brandName;
    // 企业名称
    private String companyName;
    // 排序字段
    private Integer ordered;
    // 描述信息
    private String description;
    // 状态:0:禁用  1:启用
    private Integer status;
    
}

这里的@TableName注解是依赖映射数据库对应表的名字的,如实体类名与表名一致可以不加。

创建对应的Dao接口

@Mapper
public interface BrandDao extends BaseMapper<Brand> {
}

@Repository和@Mapper的区别

  • @Repository和@Mapper都是作用在dao层的接口,使其生成代理对象Bean。
  • @Repository:需要在添加配置地址@MapperScannerConfigurer来使用,单独使用会报错
  • @Mapper:只需要在dao类上使用就行,若有多个Mapper在启动类上加MapperScan(“mapper所在的包”)就行

这里继承了MybatisPlus的BaseMapper接口,泛型内填实体类的类名

使用Mybatis进行数据层开发(CRUD)

增加数据

int insert(T t) //新增方法

编写测试案例

@SpringBootTest
class MybatisPlustTestApplicationTests {
    @Autowired
    private BrandDao brandDao;
    /**
     * 增加对象测试
     */
    @Test
    public void testInsert(){
        Brand brand = new Brand();
        brand.setBrandName("菠萝");
        brand.setCompanyName("菠萝公司");
        brand.setDescription("菠萝很好吃");
        brand.setOrdered(100);
        brand.setStatus(1);
        int insert = brandDao.insert(brand);
        if (insert > 0){
            System.out.println("添加成功");
        }else {
            System.out.println("添加失败");
        }
    }
}

​ 执行成功后数据库会生成一条数据。这个测试案例中没有给id赋值,是因为MybatisPlus的id生成策略。在yml文件中配置了auto策略。意识是跟随主键id自增。需要表中有主键并设置了主键id自生成。

​ 从以上案例可以发现,对比Mybatis,Mybatisplus简化了许多,例如无需在Dao中编写方法,也无需创建对应的xml文件。但是需知道的是,MybatisPlus是用来强化Mybati,而非替代,因此,在遇到一些MybatisPlus无法解决的场景时,也可以使用Mybatis的方法来解决。


修改数据

  • 根据id修改
int updateById(T entity);

编写测试案例

/**
 *根据id删除数据测试
 */
@Test
public void testDelete(){
    int i = 7;
    int i1 = brandDao.deleteById(i);
    if(i1 > 0){
        System.out.println("删除成功");
    }else{
        System.out.println("删除失败");
    }
}

该方法是通过id来修改的,因此对象需要有id的值。


删除数据

  • 根据id删除
  int deleteById(Serializable id);

编写案例测试

/**
 *根据id删除数据测试
 */
@Test
public void testDelete(){
    int i = 7;
    int i1 = brandDao.deleteById(i);
    if(i1 > 0){
        System.out.println("删除成功");
    }else{
        System.out.println("删除失败");
    }
}

此方法是根据id删除,所传参数为对象的id

  • 批量删除
 int deleteBatchIds(Collection<? extends Serializable> idList);

编写测试案例

/**
 * 批量删除,根据集合
 */
@Test
public void testDeleteArr(){
    List list = new ArrayList();
    list.add(13);
    list.add(14);
    list.add(15);

    int i = brandDao.deleteBatchIds(list);
    if(i > 0){
        System.out.println("删除成功");
    }else{
        System.out.println("删除失败");
    }
}

此方法根据集合删除,集合中可传入多个id值


查询数据

接下来,是最常用的查询数据

普通查询
  • 查询所有
List<T> selectList(Wrapper<T> queryWrapper);

编写测试案例

/**
 * 查询所有测试
 */
@Test
public void testGetALl(){
    List<Brand> brands = brandDao.selectList(null);
    System.out.println(brands);
}

该方法所传参数为查询条件,条件的设置后面再讲,现在先传null

  • 根据id查询
T selectById(Serializable id);

编写测试案例

    /**
     * 根据id查询数据
     */
    @Test
    public void selectById(){
        int i  = 1;
        Brand brand = brandDao.selectById(i);
        System.out.println(brand);
    }

分页查询

分页查询方法:

IPage<T> selectPage(IPage<T> page, Wrapper<T> queryWrapper)
  • IPage:用来构建分页查询条件
  • Wrapper:用来构建条件查询的条件,目前我们没有可直接传为Null
  • IPage:返回值,你会发现构建分页条件和方法的返回值都是IPage

IPage是一个接口,我们需要找到它的实现类来构建它,具体的实现类,可以进入到IPage类中按ctrl+h,会找到其有一个实现类为Page

  1. 调用方法传参获取返回值
 /**
  * 分页查询
  */
// selectPage(IPage<T> page, Wrapper<T> queryWrapper)
 @Test
 public void testSelectPage(){
     //1.创建IPage对象,1为当前页码,3为每页记录数
     IPage<Brand> iPage = new Page<>(1,3);
     //2.执行分页查询
     IPage<Brand> brandIPage = brandDao.selectPage(iPage, null);
     //3 获取分页结果
     System.out.println("当前页码值:"+iPage.getCurrent());
     System.out.println("每页显示数:"+iPage.getSize());
     System.out.println("一共多少页:"+iPage.getPages());
     System.out.println("一共多少条数据:"+iPage.getTotal());
     System.out.println("数据:"+iPage.getRecords());
 }
  1. 设置分页拦截器

这个拦截器MP已经为我们提供好了,我们只需要将其配置成Spring管理的bean对象即可。

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        //1 创建MybatisPlusInterceptor拦截器对象
        MybatisPlusInterceptor mpInterceptor=new MybatisPlusInterceptor();
        //2 添加分页拦截器
        mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mpInterceptor;
    }
}
条件查询

​ MyBatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合。

​ 这个我们在前面都有见过,比如查询所有和分页查询的时候,都有看到过一个Wrapper类,这个类就是用来构建查询条件的
​ 在进行查询的时候,我们的入口是在Wrapper这个类上,因为它是一个接口,所以我们需要去找它对应的实现类,关于实现类也有很多,说明我们有多种构建查询条件对象的方式

在这里插入图片描述

先来看第一中:QueryWrapper

/**
 * 条件查询数据(QueryWrapper)
 */
@Test
public void testGetAll(){
    //1.创建QueryWrapper对象
    QueryWrapper<Brand> qw = new QueryWrapper<Brand>();
    //2.设置查询条件,lt()代表小于号,column:字段名称,val:值
    qw.lt("ordered",100);
    List list = brandDao.selectList(qw);
    System.out.println(list);
}

​ 从上面案例看,通过QueryWrapper实体类设置好查询条件后即可进行查询,这里是通过书写字段的形式来设置条件字段的,为了避免开发时字段书写错误,可以通过Lambda的方法来进行字段的条件设置。

/**
 * 条件查询数据(QueryWrapper)
 */
@Test
public void testGetAll(){
    //1.创建QueryWrapper对象
    QueryWrapper<Brand> qw = new QueryWrapper<Brand>();
    //2.设置查询条件,lt()代表小于号,column:字段名称,val:值
   // qw.lt("ordered",100);

    //2.2使用Lambda表达式方法设置查询条件
    qw.lambda().lt(Brand::getOrdered,100);
    List list = brandDao.selectList(qw);
    System.out.println(list);
}

这种方法可以很好的避免字段字母输错的问题,但多加了个lambda()方法。

第二种方法:LambdaQueryWrapper()

/**
 * 条件查询数据(LambdaQueryWrapper)
 */
@Test
public void testGetAll2(){
    //1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<Brand> lqw = new LambdaQueryWrapper<>();
    //2.设置插叙条件
    lqw.lt(Brand::getOrdered,100);
    //3.执行查询方法
    List<Brand> brands = brandDao.selectList(lqw);
    System.out.println(brands);
}

LambdaQueryWrapper()支持使用Lambda格式的书写方式

注意:构建LambdaQueryWrapper的时候泛型不能省。

/**
 * 各种条件查询
 * * eq():等于
 * * gt():大于(>)
 * * ge():大于等于(>=)
 * * lt():小于(<)
 * * le():小于等于(<=)
 * * between():between ? and ?
 */

以上都是单个条件查询,若是有多个条件该如何构建查询条件呢?

例如:我们要查询字段status大于0并且ordered字段小于100的数据

/**
 * 多条件查询数据(LambdaQueryWrapper)
 */
@Test
public void testGetAll3(){
    //1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<Brand> lqw = new LambdaQueryWrapper<>();
    //2.设置查询条件(2个条件)
    lqw.gt(Brand::getStatus,0);
    lqw.lt(Brand::getOrdered,100);
    //3.执行查询方法
    List<Brand> brands = brandDao.selectList(lqw);
    System.out.println(brands);
}

可以看到,只需要编写两个条件就默认是&&的关系

多条件查询也支持链式编程

查找字段status大于0或ordered字段小于100的数据

/**
 * 多条件查询数据(LambdaQueryWrapper)
 * 链式编程
 */
@Test
public void testGetAll3(){
    //1.创建LambdaQueryWrapper对象
    LambdaQueryWrapper<Brand> lqw = new LambdaQueryWrapper<>();
    //2.设置查询条件(2个条件)
    lqw.gt(Brand::getStatus,0).or().lt(Brand::getOrdered,100);
    //3.执行查询方法
    List<Brand> brands = brandDao.selectList(lqw);
    System.out.println(brands);
}

当我们在不确定前端传来的条件为几个时,可以用以下方法拼接查询条件

/**
 * 动态多条件查询数据(LambdaQueryWrapper)
 */
@Test
public void testGetAll4(){
    //模拟前端传来的数据
    BrandDto brandDto = new BrandDto();
    brandDto.setOrdered(100);
    brandDto.setOrdered2(5);
    LambdaQueryWrapper<Brand> lqw = new LambdaQueryWrapper<>();
    //设置查询条件
    if(brandDto.getOrdered() != null){
        lqw.lt(Brand::getOrdered,brandDto.getOrdered());
    }
    if(brandDto.getOrdered2() != null){
        lqw.gt(Brand::getOrdered,brandDto.getOrdered2());
    }
    //执行查询方法
    List<Brand> brands = brandDao.selectList(lqw);
    System.out.println(brands);
}

上面的案例用if判空来确定查询条件,MybatisPlus还为我们提供了一种更为简便的方法

lt(boolean condition, R column, Object val);
/**
 * 动态多条件查询数据简化版(LambdaQueryWrapper)
 * condition属性
 */
@Test
public void testGetAll5(){
    //模拟前端传来的数据
    BrandDto brandDto = new BrandDto();
    brandDto.setOrdered(100);
    brandDto.setOrdered2(5);
    LambdaQueryWrapper<Brand> lqw = new LambdaQueryWrapper<>();
    //设置查询条件
    lqw.lt(brandDto.getOrdered() != null,Brand::getOrdered,brandDto.getOrdered());
    lqw.gt(brandDto.getOrdered2() != null,Brand::getOrdered,brandDto.getOrdered2());
    //执行查询方法
    List<Brand> brands = brandDao.selectList(lqw);
    System.out.println(brands);
}

此方法是原来方法的重载方法,在设置查询条件前加了一个表达式属性,当conition为true时则添加条件,为false时则不添加。

模糊查询

MybatisPlus也提供了一组模糊查询的方法

 /**
     * * like():前后加百分号,如 %J%
     * * likeLeft():前面加百分号,如 %J
     * * likeRight():后面加百分号,如 J%
     */
@Test
public void testGetAll5(){
    LambdaQueryWrapper<Brand> lqw = new LambdaQueryWrapper<>();
    //like()
    //lqw.like(Brand::getCompanyName,"科技有限");
    //likeLeft()
    lqw.likeLeft(Brand::getBrandName,"米");
    //likeRight()
    lqw.likeRight(Brand::getCompanyName,"小");
    List<Brand> brands = brandDao.selectList(lqw);
    System.out.println(brands);
}

查询投影

刚才的数据,我们都是查询所有字段相当于

select * from table

当想查询某一些字段时该使用select()方法

/**
 * 查询投影,利用select()来指定查询的字段
 */
@Test
public void testGetAll(){
    LambdaQueryWrapper<Brand> lqw = new LambdaQueryWrapper<>();
    lqw.select(Brand::getBrandName,Brand::getCompanyName,Brand::getDescription);
    lqw.gt(Brand::getOrdered,0);
    List<Brand> brands = brandDao.selectList(lqw);
    System.out.println(brands);
}
  • select(…)方法用来设置查询的字段列,可以设置多个,最终的sql语句为:

    SELECT id,name,age FROM teble
    
  • 如果使用的不是lambda,就需要手动指定字段,这里要使用QueryWrapper和表中的字段名

/**
 * 查询投影,利用select()来指定查询的字段
 */
@Test
public void testGetAll(){
    	QueryWrapper<Brand> lqw = new QueryWrapper<>();
        lqw.select("brand_name","company_name","description");
        lqw.gt("ordered",0);
        List<Brand> brands = brandDao.selectList(lqw);
        System.out.println(brands);
}

聚合函数
需求:聚合函数查询,完成count、max、min、avg、sum的使用

count:总记录数

max:最大值

min:最小值

avg:平均值

sum:求和
/**
 * 聚合函数
 */
@Test
public void testGetAll2(){
   QueryWrapper<Brand> lqw = new QueryWrapper<>();
    lqw.select("count(*) as count");
    List<Map<String, Object>> maps = brandDao.selectMaps(lqw);
    System.out.println(maps);
}
分组查询
/**
 * 分组查询
 */
@Test
public void testGetAll3(){
    QueryWrapper<Brand> qw = new QueryWrapper<>();
    qw.select("count(*) as count,ordered");
    qw.groupBy("ordered");
    List<Map<String, Object>> maps = brandDao.selectMaps(qw);
    System.out.println(maps);
}

这个查询方法相当于sql语句:

select count(*) as count,ordered from tb_brand group by ordered;
排序查询
orderBy(boolean condition, boolean isAsc, R... columns)
 /**
     * condition :条件,返回boolean,
     		当condition为true,进行排序,如果为false,则不排序
     * isAsc:是否为升序,true为升序,false为降序
     * columns:需要操作的列
     */
    /**
     * 根据id排序查询
     */
    @Test
    public void testOrder(){
        LambdaQueryWrapper<Brand> lqw = new LambdaQueryWrapper<>();
        lqw.orderBy(true,false,Brand::getId);
        List<Brand> brands = brandDao.selectList(lqw);
        System.out.println(brands);
    }

MybatisPlus中的Service开发

刚刚都是编写Dao层的开发,在一边的service层开发,都是写好service接口和serviceImpl实现类,再再serviceImpl实现类中注入Dao实体类,实现service接口的方法。如下:

/**
*service接口
*/
public interface UserService{
	
}
/**
*service实现类
*/
@Service
public class UserServiceImpl implements UserService{

}

接口和实现类有了以后,需要在接口和实现类中声明方法

public interface UserService{
	public List<User> findAll();
}

@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserDao userDao;
    
	public List<User> findAll(){
        return userDao.selectList(null);
    }
}

MybatisPlus提供了一个Service接口和实现类,分别是:IServiceServiceImpl,后者是对前者的一个具体实现。具体使用方式如下:

  • service接口
public interface BrandService extends IService<Brand> {
}
  • serviceImpl实现类
@Service
public class BrandServiceImpl extends ServiceImpl<BrandDao, Brand> implements BrandService {
}
  • 测试案例
@SpringBootTest
public class MybatisPlustTest3 {
    
    @Autowired
    private BrandService brandService;
    /**
     * 查询所有
     */
    @Test
    public void testService(){
        List<Brand> list = brandService.list(null);
        System.out.println(list);
    }
}

修改以后的好处是,MP已经帮我们把业务层的一些基础的增删改查都已经实现了,可以直接进行使用。至于更复杂的方法,可以通过在service接口写方法并实现的办法实现。MP封装的Service层都有哪些方法可以用可以在MybatisPlus官网查看

https://www.baomidou.com/

最后再提示:MybatisPlus不是替代Mybatis,它旨在加强mybatis,使开发者在开发一些基础的方法时可以更为便捷的实现,在MP环境下也可以使用mybatis的各种方法

体使用方式如下:

  • service接口
public interface BrandService extends IService<Brand> {
}
  • serviceImpl实现类
@Service
public class BrandServiceImpl extends ServiceImpl<BrandDao, Brand> implements BrandService {
}
  • 测试案例
@SpringBootTest
public class MybatisPlustTest3 {
    
    @Autowired
    private BrandService brandService;
    /**
     * 查询所有
     */
    @Test
    public void testService(){
        List<Brand> list = brandService.list(null);
        System.out.println(list);
    }
}

修改以后的好处是,MP已经帮我们把业务层的一些基础的增删改查都已经实现了,可以直接进行使用。至于更复杂的方法,可以通过在service接口写方法并实现的办法实现。MP封装的Service层都有哪些方法可以用可以在MybatisPlus官网查看

https://www.baomidou.com/

最后再提示:MybatisPlus不是替代Mybatis,它旨在加强mybatis,使开发者在开发一些基础的方法时可以更为便捷的实现,在MP环境下也可以使用mybatis的各种方法

网站文章

  • SLS机器学习最佳实战:日志聚类+异常告警

    SLS机器学习最佳实战:日志聚类+异常告警

    2019独角兽企业重金招聘Python工程师标准>>> ...

    2024-02-01 00:31:14
  • 在ubuntu系统中删除软件的三种最佳方法

    在ubuntu系统中删除软件的三种最佳方法

    三种方法分别是:1、通过软件中心删除 2、通过Synaptic Package Manager删除 3、通过命令行删除三种方法的详细介绍一、ubuntu software 1、点击左侧菜单栏上的“ubuntu software” 2、在软件中心界面,点击“installed”,可以列出已经安装过的软件。 3、软件右侧,有"remove"功能。 4、选中需要删除的软件,...

    2024-02-01 00:31:07
  • DataBinding实战(三)

    实战首先看一下之前代码public class Goods { public String name; public String details; public float price; public Goods(String name, String details, float price) { this.name = na...

    2024-02-01 00:31:00
  • 构建高效的软件测试知识体系

    2018年6月8日,作为第一届TMMi中国峰会圆桌会议的嘉宾,我参与讨论了“如何建立适合测试组织的测试规范体系”这个测试主题,其中分享了我对该话题的一些想法和经验。现在通过文章的方式将当时讲解的内容进行了一些归纳和总结,主要包括3个方面的内容: 1个故事:任何问题的解决都需要从过个层面考虑; 4个维度:构建高效的软件测试知识体系; 目标推动:综合应用4个维度推动测试目标的...

    2024-02-01 00:30:32
  • el-select 下拉框数量过多的处理方法之一

    Element-ui 下拉列表 选项过多时如何解决卡顿问题 当使用Select选择器时,如果下拉列表有几千个几万个,因此通过滚动条一个个的去找不是很现实, 这时可以对select设置filterable属性,可以在下拉控件里进行搜索。例如:

    2024-02-01 00:30:25
  • 带你正确认识Unicode和UTF-8

    带你正确认识Unicode和UTF-8

    前言 相信很多小伙伴跟我一样,之前很长一段时间对Unicode和UFT-8一直搞得不清不楚,等到用的时候就网上搜一搜,大概懂了点是什么,隔一段时间后又搞忘了,简直阔怕啊。今天我将带您轻轻松松出困境,用...

    2024-02-01 00:30:17
  • 【Redis】Redis布隆过滤器安装

    【Redis】Redis布隆过滤器安装

    Redis布隆过滤器安装

    2024-02-01 00:29:48
  • 一篇文章理解AB测试和灰度发布

    一篇文章理解AB测试和灰度发布

    一、灰度发布1.1 简介灰度发布,是指黑与白之间,能够平滑过渡的一种发布方式。通过不同策略对用户进行分流,不同的用户组使用不同的应用版本。1.2 优缺点优点互联网服务变动频繁,发布周期短。速度和质量总是难以双全。灰度发布有以下优点:(1)降低发布风险,减少影响范围(2)可以灰度测试账号,降低测试依赖,减少自测的数据构造成本(3)方便回滚缺点(1)开发、...

    2024-02-01 00:29:39
  • mybatis入门实践1)

    mybatis入门

    2024-02-01 00:29:22
  • 评估目标跟踪算法

    一、OTB评估指标 OTB 可以用来衡量你的目标跟踪算法好坏,它包含一些 benchmark 结果,打好标记(即ground-truth.txt )的数据集,以及一个用来测试你的算法的代码库。 数据集...

    2024-02-01 00:29:06