SpringBoot&MyBatisPlus

MyBatisPlus

1.1MyBatisPlus简介

MyBatisPlus是基于MyBatis的框架的基础上开发的增强型工具,它简化开发,将一些增删改查的写好封装到BaseMapper,你只需要继承BaseMapper,就可以调用其的方法,一些简单的sql语句不在用手动编写,可以与MyBatis配合使用,提升工作效率

MyBatis官网: MyBatis-Plus (baomidou.com)

MyBatisPlus特性(官方网站):

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

1.2MyBatisPlus入门程序

MyBatisPlus可以和spring、springMVC、springBoot进行整合使用,应为在大多数开发中使用springBoot框架的居多,所以我们使用springBoot来整合MyBatisPlus。

我们要在pom.xml文件中导入MyBatisPlus依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.1</version>
</dependency>

我在这个入门程序中使用的是Druid数据源,所以我们也要导入Druid数据源的依赖(SpringBoot&整合Druid数据源: SpringBoot&整合Druid数据源_springboot 整合druid_一路向北…的博客-CSDN博客

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.16</version>
</dependency>

application.yaml配置

spring:
  datasource:
    username: root
    password:
    url: jdbc:mysql://localhost:3306/dbs?&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
#开启MyBatisPlus的日志(输出到控制台)
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl    

我的数据库表
在这里插入图片描述
在springBoot项目中创建实体类,我使用了lombok,可以简化实体类中的操作

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

Student

package com.gao.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private int id;
    private String name;
    private int age;
    private int cid;
}

在dao层中创建接口来实现增删改查方法,用来继承BaseMapper类。其中BaseMapper的类型为你的实体类,在BaseMapper中封装许多的增删改查方法,可以根据自己的需求进行调用。
在这里插入图片描述
StudentDao

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.gao.pojo.Student;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface StudentDao extends BaseMapper<Student> {

}

在测试类中进行测试,就可以输出结果了。

Demo01ApplicationTests

import com.gao.dao.StudentDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class Demo01ApplicationTests {
    @Autowired
    StudentDao studentDao;

    @Test
    void contextLoads() {
        //查询所有的方法
        System.out.println(studentDao.selectList(null));
    }

}

在这里插入图片描述

1.3MyBatisPlus分页查询定制

我们找到selectPage方法发现,它需要一个Page对象
在这里插入图片描述
selectPage的源代码中可以看到这个Page对象是一个IPage的对象

<E extends IPage<T>> E selectPage(E page, @Param("ew") Wrapper<T> queryWrapper);

IPage是一个接口,需要有一个是实现类,IPage接口只有一个实现类Page
在这里插入图片描述

   @Test
    void page(){
        //               页码设置:当前第一页每页2条
        IPage page = new Page(1,2);
        studentDao.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());

    }

但是我们只用次方法是不能实现分页查询的,我们只能查询出表的全部数据,我们要配置一个MyBatisPlus的拦截器,拦截并开启一个分页拦截器,此操作类似于AOP。

在Config层创建StudentConfig来配置拦截器

StudentConfig

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 StudentConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        //1.定义MyBatisPlus拦截器
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        //添加具体的拦截器 (在这里可以根据自己的需求添加不同的拦截器)
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

当我们完成拦截器的配置后,我们的分页查询功能就可以实现了。
在这里插入图片描述

1.4DQL编程控制

1.1条件查询三种格式

 // 按条件查询
    @Test
    void test1(){
        //方式一:按条件查询
        QueryWrapper qw = new QueryWrapper();
        qw.lt("age",29);
        List<Student> list = studentDao.selectList(qw);
        System.out.println(list);
    }


    //按条件查询
    @Test
    void test2(){
        //方式二:lambda格式按条件查寻
        QueryWrapper<Student> qw = new QueryWrapper();
        qw.lambda().lt(Student::getAge,31);
        List<Student> list = studentDao.selectList(qw);
        System.out.println(list);
    }

    @Test
    void test3(){
        //方式三
        LambdaQueryWrapper<Student> lqw = new LambdaQueryWrapper<>();
        //小于29大于10
        lqw.lt(Student::getAge,30).gt(Student::getAge,10);
        //小于10大于29
        //lqw.lt(Student::getAge,10).or().gt(Student::getAge,29);
        List<Student> list = studentDao.selectList(lqw);
        System.out.println(list);
    }


1.2查询投影

查询投影是指你查询出的数据有的个字段。

 //查询投影
    @Test
    void test4(){
        LambdaQueryWrapper<Student> lqw = new LambdaQueryWrapper<>();
        //只查询getId、getName两个字段数据
        lqw.select(Student::getId,Student::getName);
        List<Student> list = studentDao.selectList(lqw);
        System.out.println(list);
    }

从输出的结果和sql语句可以看出,查询得到的字段只有ID和name,查询投影可以用来单独查询一个表中一个或多个字段。

在这里插入图片描述
在这里插入图片描述
注意:

lqw.select(Student::getId,Student::getName);此种格式只适用lambda格式,如果使用QueryWrapper的方式就需要字符串的形式qw.select(“id,name”);

查询投影也可以用来做分组统计,但是必须用QueryWrapper的方式来实现。

void test2(){
    //方式二:lambda格式按条件查寻
    QueryWrapper<Student> qw = new QueryWrapper();
    //as count(别名)
    qw.select("count(*) as count,cid");
    //查询cid相同的数据
    qw.groupBy("cid");
    //此处选择Map集合来存储,因为之前使用的list集合是一个Student实体类类型,count参数传不进去,就会返回空值
    List<Map<String, Object>> list = studentDao.selectMaps(qw);
    System.out.println(list);
}

1.3查询条件设置

1.登录

简单的写一个登录的条件,eq就相当于equals。如果我们给的条件在数据库中查不到,就会返回null,登陆失败,反之登录成功。

@Test
void test5(){
    LambdaQueryWrapper<Student> lqw = new LambdaQueryWrapper<>();
    //条件:一个登录的方法
    lqw.eq(Student::getName,"克莱").eq(Student::getAge,11);
    //只查询一条数据
    Student loginStu = studentDao.selectOne(lqw);
    System.out.println(loginStu);

}

2.范围查询

@Test
void test5(){
    LambdaQueryWrapper<Student> lqw = new LambdaQueryWrapper<>(){
        //使用此方法时要注意范围要先写小的后写大的
        lqw.between(Student::getAge,10,30);
        List<Student> list = studentDao.selectList(lqw);
        System.out.println(list);

    }

3.模糊匹配

//模糊匹配
@Test
void test6(){
    LambdaQueryWrapper<Student> lqw = new LambdaQueryWrapper<>();
    lqw.like(Student::getName,"克");
    List<Student> list = studentDao.selectList(lqw);
    System.out.println(list);
}

条件有许多种,这里我只列举三种比较常用的条件,具体的请到官网进行查看。

1.4字段映射与表名映射

在我们开发过程中,如果你的实体类属性名与数据库中的字段列表名不同,但是又不想大费周章的更改,我们就可以使用**@TableField**注解,进行修改,简单便捷。

@TableField(value = "username")
private String name;

我们还可以利用**@TableField**注解来设置一些字段是否在数据库表中存在,默认为true,即为存在,false则为不存在。

@TableField(exist = false)
private int abc;

可以用**@TableField来设置哪些字段不参与一些sql语句查询,其原理大致与exist**相同。

@TableField(select = false)
private int abc;

1.5DML编程控制

1.1id生成策略控制

在我们进行对数据库添加表操作时,id会有不同的生成策略,可以主键自增,也可以自定义它自增的方式。、

  • AUTO:使用数据库id自增策略控制id生成
  • NONE:不设置id生成策略
  • INPUT:用户手动输入id
  • ASSIGN_ID:雪花算法生成id(可兼容数值型和字符串型),雪花算法大概意思就是随机生成一个long类型的数。
  • ASSIGN_UUID:以UUID生成算法作为id生成策略。

用法:在实体类id这个属性上使用@TableId

@TableId(type = IdType.AUTO)
private int id;

简化

在现实中,我们一个项目大概要许多给实体类,如果我们控制id生成策略,就可以在配置文件中进行配置,以免去在每个实体类中都要完成相同且重复的操作。配置完成,这个id生成策略就可以在所有类中生效。

application.yaml配置:

spring:
  datasource:
    username: root
    password:
    url: jdbc:mysql://localhost:3306/dbs?&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
#开启MyBatisPlus的日志(输出到控制台)
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    banner: false
    db-config:
      id-type: assign_id

1.2删除操作(多条数据同时删除)

//多条数据删除
@Test
void delete(){
    //根据id进行多条数据删除
    List<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    studentDao.deleteBatchIds(list);

}

1.3乐观锁

乐观锁使用来解决并发问题得,在我们得生活中使用购物软件时,会遇到一些限量商品,当商品销售到只剩下一个的时候,就可能有多个人来购买这一个商品,如果没有锁的作用,就可能出现负数的商品,为了避免这一情况的发生,锁就显得非常重要了。

程序讲解

  • 首先要在数据库表中加入一个version字段默认值为1,每当我们执行修改语句时version就会
    +1。

  • 在实体类中声明属性,并且加上注解。

    @Version
    private int version;
    
  • 在Config中加入乐观锁的拦截器,实现锁机制对应的动态sql语句拼装。

    //乐观锁拦截器
    mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    
  • 在测试代码中进行测试

    @Test
    void test10(){
        Student student = studentDao.selectById(6);//version=2
    
        Student student1 = studentDao.selectById(6);//version=2
    
        student1.setName("尼古拉斯");
        studentDao.updateById(student1);  //version=>3
    
        student.setName("克拉克斯顿");  //此时version=2是否还成立已经不成立了
        studentDao.updateById(student);
    }
    

    当student1执行之后version=3,当student执行之时,version已经=3,就不再满足条件了,所以student就会失效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值