【SpringBoot】【MybatisPlus】技术详解

发布于:2025-09-06 ⋅ 阅读:(11) ⋅ 点赞:(0)

SpringBoot

需要达到的学习效果:

  • 1.掌握基于SpringBoot框架的程序开发步骤
  • 2.熟练使用SpringBoot配置信息修改服务器配置
  • 3.基于SpringBoot完成SSM的整合项目开发

1.初始化

  • 1.创建新模块,选择Spring初始化,并配置模块的基础信息

在这里插入图片描述

  • 2.使用Spring Web进行SpringMvc的开发:
    在这里插入图片描述
  • 3.开发控制类,定义控制器:(REST风格)
@RestController
@RequestMapping("/books/")
public class BookController {
    @PostMapping("{id}")
    public String getById(@PathVariable Integer id) {
        System.out.println("id === " + id);
        return "success";
    }
}
  • 4.运行自动生成的Application类:
    在这里插入图片描述

2.Spring与SpringBoot程序开发对比

在这里插入图片描述

  • 基于idea开发SpringBoot框架需要联网
    另外一种方式就是通过Spring的官网进行生成:(不用idea照样生成工程)
    在这里插入图片描述

0.快速启动

  • 脱离idea启动一个SpringBoot程序
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

1.SpringBoot概述

  • 用于简化Spring应用的初始搭建和开发过程
  • Spring程序的缺点:
    • 配置繁琐
    • 依赖设置繁琐
  • SpringBoot解决的问题:
    • 自动配置
    • 起步依赖(简化依赖配置)
    • 辅助功能(内置服务器)
  • pom文件中已经帮我们提前做好了版本管理以及对应的依赖管理
1.起步依赖:

在pom文件中只有简单的几个起步依赖,就可以完成整个工程项目所需的基本配置:
在这里插入图片描述
而在<parent>spring-boot-start-parent</parent>中,他对应继承了
<parent>spring-boot-dependencies</parent>
在这里插入图片描述
<parent>spring-boot-dependencies</parent>中,他配置了各种版本管理,以及依赖管理:

在这里插入图片描述

  • GAV:
    • groupId
    • artifactId
    • version
      在这里插入图片描述
  • 在企业应用中,需要根据使用的Spring版本去找对应的SpringBoot版本是多少
2.辅助功能

在这里插入图片描述

3.启动方式

在这里插入图片描述

4.使用maven依赖管理变更起步依赖项

spring-boot-start-web下将tomcat排除:<exclusions><exclusion>spring-boot-starter-tomcat</exclusion></exclusions>
在这里插入图片描述

5.配置格式
  • 直接在application.properties
  • 配置application.yml
  • 配置application.yaml
    在这里插入图片描述

三个文件同时存在时,生效顺序:properties > yml > yaml
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

1)YAML文件

在这里插入图片描述

  • yaml语法规则:
    • 1.大小写敏感
    • 2.属性层级关系使用多行描述,每行结尾使用冒号结束
    • 3.使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用Tab键)
    • 4.属性值前面添加空格(属性名与属性值之间使用冒号+空格作为分隔)
    • #表示注释
2.yaml数据读取方式
  • 1.使用@Vaule读取单个数据,属性名引用方式: ${一级属性名.二级属性名}

  • 2.封装全部数据到Enviment对象

在这里插入图片描述

  • 3.自定义对象封装指定数据

在这里插入图片描述

在这里插入图片描述

2.多环境开发

  • yaml多环境开发配置:
    在这里插入图片描述

  • properties文件多环境开发配置:
    在这里插入图片描述

1.多环境启动命令格式

执行package打包之前,最好先clean一下
有其他干扰配置文件时,应该将它放到备份里面,防止对自己的设置冲突

  • 1.java -jar springboot.jar -- spring.server.active=dev

  • 2.命令行修改参数配置:
    java -jar springboot.jar --server.port=88

  • 当设置的配置没有生效时,需要去检查一下参数的优先级,是否被其他优先级高的替换掉了
    在这里插入图片描述

在这里插入图片描述

3.整合Junit

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.整合Mybatis

  • 1.表现层实现:这里是使用测试类来实现
@SpringBootTest
class SpringbootMybatisDemoApplicationTests {


    @Autowired
    private BookDao bookDao;

    @Test
    void getById() {
       Book book =  bookDao.getBookById(1);
        System.out.println(book);
    }

}
  • 2.数据层接口映射配置:
@Mapper
public interface BookDao {

    @Select("select * from tb_book where id = #{id}")
    public Book getBookById(Integer id);
}
  • 3.数据库连接配置以及Druid数据源设置:
    导入druid数据源坐标:
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db
    username: root
    password: 123456
    type: com.alibaba.druid.pool.DruidDataSource

MybatisPlus

1.简介

  • 基于Mybatis框架基础上开发的增强型工具,旨在简化开发,提高效率
  • SpringBoot整合Mybatis开发过程:
    • 创建SpringBoot工程
    • 勾选配置使用技术
    • 设置dataSource相关属性(JDBC参数)
    • 定义数据层接口映射配置

2.特性

  • 无侵入:只增强,不改变现有工程
  • 强大的CRUD操作,内置通用Mapper,少量配置可以实现单表CRUD操作
  • 支持Lambda:编写查询条件无需担心字段写错
  • 支持主键自动生成
  • 内置分页插件

3.标准CRUD开发

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

@SpringBootTest
class Mybatisplus01QuickstartApplicationTests {

    @Autowired
    private UserDao userDao;


    @Test
    void testGetById(){
        User user = userDao.selectById(1L);
        System.out.println(user);
    }


    @Test
    void testGetAll() {
        List<User> userList = userDao.selectList(null);
        System.out.println(userList);
    }

    @Test
    void testInsert() {
        User user = new User();
        user.setName("wangwu");
        user.setPassword("123456");
        user.setAge(34);
        user.setTel("123456566");
        userDao.insert(user);
    }

    @Test
    void testDelete() {
        userDao.deleteById(1L);
    }

    @Test
    void testUpdate() {
        User user = new User();
        user.setId(1L);
        user.setName("lisi");
        user.setPassword("123456");
        user.setAge(34);
        user.setTel("123456566");
        userDao.updateById(user);
    }
}
1)MybatisPlus提供的查询分页
  • 提供了一个接口Ipage

  • 设置分页拦截器作为Spring管理的Bean:

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        //1,定义MybatisPlus的拦截器
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //2. 添加具体的拦截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}
  • 分页查询:可以在Ipage的对象中获取到当前页面是第几页,每页显示的数量,总页数,所有数据以及当前页面的具体数据
@SpringBootTest
class Mybatisplus01QuickstartApplicationTests {

    @Autowired
    private UserDao userDao;
    @Test
    void testPage() {
        IPage page = new Page<>(1, 1);
        userDao.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());
    }
}

在这里插入图片描述

2)按条件查询
  • MybatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合
@SpringBootTest
class Mybatisplus01QuickstartApplicationTests {

    @Autowired
    private UserDao userDao;
    @Test
    void testSelectByCondition() {

        //方式一:
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.lt("age", 50);
        List<User> userList = userDao.selectList(qw);
        System.out.println(userList);

        
        //方式二:lambda格式的条件查询
        QueryWrapper<User> qw1 = new QueryWrapper<>();
        qw1.lambda().lt(User::getAge, 20);
        List<User> userList1 = userDao.selectList(qw1);
        System.out.println(userList1);


        //方式三:lambda的api格式
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.gt(User::getAge, 20);
        List<User> userList2 = userDao.selectList(lqw);
        System.out.println(userList2);

    }
}
  • 多条件:

查询age在20到30之间的数据:

        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.gt(User::getAge, 20).lt(User::getAge, 30);
        List<User> userList2 = userDao.selectList(lqw);
        System.out.println(userList2);

查询age大于30或者小于20的数据:

        LambdaQueryWrapper<User> lqw1 = new LambdaQueryWrapper<>();
        lqw.gt(User::getAge, 30).or().lt(User::getAge, 20);
        List<User> userList3 = userDao.selectList(lqw1);
        System.out.println(userList3);

在这里插入图片描述

3)null值处理
  • 在进行范围匹配查询时,我们通常是通过接收用户选定的两个范围值来确定范围
  • 但是如果用户只选了一侧的范围值的话,另一侧就会以null的形式传递过来
  • 我们通常是通过if判断该值是否为空,从而看是否追加该侧的条件:
    在这里插入图片描述
  • 这里MybatisPlus提供了更为简洁的方式:
    在传递条件前,设立一个条件,如果满足条件为true,才连接当前查询条件,否则不连接该条件
@SpringBootTest
class Mybatisplus01QuickstartApplicationTests {

    @Autowired
    private UserDao userDao;
    
    @Test
    void testSelectByCondition() {
        UserQuery uq = new UserQuery();
        //模拟页面传递过来的查询数据
        uq.setAge(20);   //条件1
       // uq.setAge2(30); //条件2

        LambdaQueryWrapper<User> lqw2 = new LambdaQueryWrapper<>();
        lqw2.gt(null != uq.getAge2(), User::getAge, uq.getAge2());
        lqw2.lt(null != uq.getAge(),User::getAge, uq.getAge());
        List<User> userList4 = userDao.selectList(lqw2);
        System.out.println(userList4);o.selectList(lqw);
        System.out.println(userList2);
    }
}
4)查询投影
  • 查询结果包含模型类中部分属性:
@SpringBootTest
class Mybatisplus01QuickstartApplicationTests {

    @Autowired
    private UserDao userDao;
    
    @Test
    void testSelectByWrapper() {
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
        lqw.select(User::getId, User::getName, User::getAge);
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
    }

}
  • 查询结果包含模型中未定义的属性:
@SpringBootTest
class Mybatisplus01QuickstartApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testSelectByWrapper2() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.select("count(*) as count, tel");
        qw.groupBy("tel");
        List<Map<String, Object>> mapList = userDao.selectMaps(qw);
        System.out.println(mapList);
    }
}
5)其他条件查询
  • 等匹配:eq()
  • 以及其他:lt() le() gt() between()
@SpringBootTest
class Mybatisplus01QuickstartApplicationTests {

    @Autowired
    private UserDao userDao;
    @Test
    void testLogin() {
        QueryWrapper<User> qw = new QueryWrapper<>();
        qw.eq("name", "黑马程序员").eq("password", "itheima");
        User user = userDao.selectOne(qw);
        System.out.println(user);
    }
}

在这里插入图片描述

6)字段映射与表名映射
  • 数据库表字段与编码时的属性设计不同:
    在这里插入图片描述

在这里插入图片描述

  • 2.编码时添加了数据库中未定义的属性:
    在这里插入图片描述

在这里插入图片描述

  • 采用默认查询开放了更多字段的查看权限:
    在这里插入图片描述
    在这里插入图片描述

  • 表名与实体类名不一致:

在这里插入图片描述
在这里插入图片描述

4.id生成策略控制

1)id生成

  • 不同的表应用时需要不同的id生成策略:
    在这里插入图片描述
  • 注解:@TableId
    在这里插入图片描述
  • AUTO(0):使用数据库id自增策略控制id生成
  • NONE(1):不设置id生成策略
  • INPUT(2):用户手工输入id(不能为null)
  • ASSIGN_ID(3):雪花算法生成id(可兼容数值型与字符串型)
  • ASSIGN_UUID(4):以UUID生成算法作为id生成策略
    在这里插入图片描述
2)全局设置
  • 每个实体类上都需要配置@TableId
  • 数据库中表名一般有前缀:比如tb_xxx,每个表都需要加入@TableName("tb_xxx")
  • 为了简化:直接在全局进行配置:
mybatis-plus:
  global-config:
    banner: false
    db-config:
      #全局配置表的id生成策略为:雪花算法生成策略
      id-type: assign_id
      #设置全表的前缀拼接“tb_"
      table-prefix: tb_
  • 原本需要在表的实体类User上加@TableName("tb_user"),在全局配置中加上表的前缀之后,就可以去除注解,直接匹配

5.多记录操作

  • 按多个id进行删除:deleteBatchIds() 传入id数组
  • 按多个id进行查询:selectBatchIds()

6.逻辑删除

  • @TableLogic:逻辑删除字段,标记当前记录是否被删除

  • 正常数据删除时,对应的关联数据也会进行删除

  • 但是对应总的订单数等业务统计数据,删除数据会对业务造成损失,业务数据从数据库中丢弃

  • 逻辑删除:为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,数据保留在数据库中

  • 比如:当员工张业绩离职时,需要删除他对应的信息,那么他关联的销售业绩也需要对应删除

在这里插入图片描述

  • 但是当统计总的销售金额时,数据被删除就无法统计出真正的销售总额
    在这里插入图片描述

逻辑删除配置流程

  • 1.在对应表中新增字段deleted默认值为0
    在这里插入图片描述

  • 2.配置该字段为逻辑删除字段

    • 方式一:@TableLogic(value = "0", deval = "1"),标记删除为1,没有删除则为0
@Data
public class User {
    //根据雪花算法生成Id
    //当未传入id时,会自动根据雪花算法生成Id
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;

    @TableLogic(value = "0", delval = "1")
    private Integer deleted;
}

* 方式二:全局配置:
mybatis-plus:
  global-config:
    banner: false
    db-config:
      logic-delete-field: deleted
      logic-delete-value: 1
      logic-not-delete-value: 0
  • 3.编写测试代码:
@SpringBootTest
class Mybatisplus01QuickstartApplicationTests {

    @Autowired
    private UserDao userDao;
    @Test
    void testDeleted() {
        userDao.deleteById(1963561718751342594L);
    }
}
  • mybatisplus中执行的其实是update语句:
    在这里插入图片描述

7. mybatis乐观锁设置

  • 1.添加锁标记字段:默认为1
    在这里插入图片描述
  • 2.实体类添加对应字段,并设定当前字段为版本更新字段@Version
@Data
public class User {
    //根据雪花算法生成Id
    //当未传入id时,会自动根据雪花算法生成Id
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;
    private Integer deleted;
    
    @Version
    private Integer version;
}
  • 3.配置乐观锁拦截器,实现锁机制对应的动态SQL拼装:也就是在执行更新SQL之前拼接version字段的条件:
@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        //1,定义Mybatis的拦截器
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //2. 添加分页查询的拦截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());

        //3. 添加乐观锁拦截器
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}
  • 4.使用乐观锁机制在修改前必须先获取到对应数据的version方可正常进行:
@SpringBootTest
class Mybatisplus01QuickstartApplicationTests {

    @Autowired
    private UserDao userDao;
    @Test
    void testOptimisticLock() {
        //先查询数据,获取到version数据
        User user = userDao.selectById(1963562661970673666L);
        //执行数据修改操作
        user.setName("Tom999");
        userDao.updateById(user);
    }
}

在这里插入图片描述

  • 执行时会根据获取的version去查对应的数据,然后操作完之后将version+ 1

在这里插入图片描述

乐观锁实现机制

在这里插入图片描述

  • 首先模拟了a和b并发去获取同一条数据的情况:
@SpringBootTest
class Mybatisplus01QuickstartApplicationTests {

    @Autowired
    private UserDao userDao;
    @Test
    void testOptimisticLock() {
        //a 和 b同时修改同一条数据
        User user_a = userDao.selectById(1963577811377319938L); //version == 2

        User user_b = userDao.selectById(1963577811377319938L); //version == 2

        //a先执行数据修改操作
        user_a.setName("lisi"); //version == 2
        userDao.updateById(user_a);  //version => 3

        //b再修改
        user_b.setName("zhaoliu");  //此时已经找不到version为2的数据了
        userDao.updateById(user_b);
    }
}
  • 当a和b获取到同一条数据后,他们此时的version都是为2,而当a先提交之后,通过拦截器会先根据version = 2查询到当前记录并动态拼接SQL将当前记录的version修改为3
  • 而当b再提交时,拦截器通过version = 2已经查不到对应的数据了,就无法进行修改
  • 这样就避免了并发下,两个操作同时修改同一条记录的问题
    在这里插入图片描述

8.代码生成器

  • 1.添加依赖:mybatis-plus-generatorMybatisPlus关于代码生成器的依赖以及velocity-engine-core生成代码的核心引擎:
    在这里插入图片描述

  • 2.创建生成器:

  • 1)数据源的指定:

package com.itheima;

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;

public class Generator {
    public static void main(String[] args) {
        AutoGenerator autoGenerator = new AutoGenerator();

        DataSourceConfig dataSource = new DataSourceConfig();
        dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        autoGenerator.setDataSource(dataSource);

        autoGenerator.execute();
    }
}

  • 2)全局配置的指定:指定生成的文件路径,包名,是否覆盖等
    在这里插入图片描述
  • 3)包相关配置指定:每个包对应的名称
    在这里插入图片描述
  • 4)策略相关配置指定:指定需要生成的表,设置逻辑删除字段,乐观锁字段等在这里插入图片描述

*注:上述内容来自B站黑马程序员视频的学习截图,仅作为学习交流,不用作商业用途,如有侵权,联系删除。


网站公告

今日签到

点亮在社区的每一天
去签到