5. SpringBoot

  • 学习目标:

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

5.1 入门案例

SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程

  • 原生开发SpringSSM程序过程

    • 创建工程,在pom中配对应的依赖
    • 添加Spring、MyBatis、SpringMVC的相关配置类
    • 添加Controller类、Service类、Dao
  • 实现步骤:

    • 创建工程

    • 编写controller

    • 运行Application

  • 最简SpringBoot程序所包含的基础文件

    • pom.xml文件

      <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion> <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version> 2.7.3</version>
      <relativePath/> <!-- lookup parent from repository -->
      </parent> <groupId>com.mark</groupId>
      <artifactId>SpringBoot_01_QuickStart</artifactId>
      <version>0.0.1-SNAPSHOT</version> <properties>
      <java.version>11</java.version>
      </properties> <dependencies>
      <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      </dependencies>
      </project>
    • Application类

      @SpringBootApplication
      public class Application {
      public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
      }
      }
  • Spring程序与SpringBoot程序对比

  • 基于idea开发SpringBoot程序需要确保联网且能够加载到程序框架

5.2 SpringBoot工程官网创建方式

5.3 SpringBoot项目快速启动

  • 对SpringBoot项目打包(执行Maven构建指令package)

  • 执行启动指令

    java -jar springboot.jar

注意事项:

jar支持命令行启动需要依赖maven插件支持,需要确认在打包时是否具有SpringBoot对应的maven插件

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.3</version>
</plugin>
</plugins>
</build>

5.4 SpringBoot概述

SpringBoot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程

  • Spring程序缺点

    • 配置繁琐
    • 依赖设置繁琐
  • SpringBoot程序优点

    • 自动配置
    • 起步依赖(简化依赖配置)
    • 辅助功能(内置服务器,...)
  • 起步依赖帮助我们实现了快速配置

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.3</version>
    </parent>
    <groupId>com.mark</groupId>
    <artifactId>SpringBoot_01_QuickStart</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
    <java.version>11</java.version>
    </properties>
    <dependencies>
    <!--起步依赖-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    </dependencies>
    </project>
    • starter

      • SpringBoot中常见项目名称,定义了当前项目使用的所有项目坐标,以达到减少依赖配置的目的
    • partent
      • 所有SpringBoot项目要继承的项目,定义了若干个坐标版本号(依赖管理,而非依赖),以达到减少冲突的目的
      • spring-boot-starter-parent(2.5.0)与spring-boot-starter-parent(2.4.6)共计57处坐标版本不同
  • 实际开发

    • 使用任意坐标时,仅书写VGA中的G和A,V由SpringBoot提供
    • 如发生坐标错误,再指定version(要小心版本冲突)
  • SpringBoot启动

    • 启动方式

      @SpringBootApplication
      public class Application {
      public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
      }
      }
    • Spring在创建项目时,采用jar的打包方式

    • SpringBoot的引导类是项目的入口,运行main方法就可以启动

5.5 Spring辅助功能:切换web服务器

使用jetty替换tomcat:使用maven依赖管理变更起步依赖项

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

Jetty比Tomcat更轻量级,可扩展性更强(相较于Tomcat),谷歌搜索引擎(GAE)已经全面切换为Jetty

5.6 配置文件格式

  • 修改服务器端口

    http://localhost:8080/books/1

    修改为80端口号:http://localjost/books/1

  • SpringBoot提供了多种属性配置方式

    • application.properties中修改

      在resources下的application.properties添加server.port=80

    • application.yml中修改

      在resources下新建application.yml文件,添加server:port:80

    • application.ymal中修改

      在resources下新建application.yaml文件,添加server:port:80

  • 注意:

    • 在之后主要在application.yml中修改配置
    • 如果三个文件都存在,properties为第一配置文件,yml为第二配置文件,yaml为第三配置文件。即如果三个文件有相同的配置,优先级为properties->yml->yaml

5.7 yaml格式

  • YAML(YAML Ain't Markup Language):一种数据序列化格式

  • 优点:

    • 容易阅读
    • 容易与脚本语言交互
    • 以数据为核心,重数据轻格式
  • YAML文件扩展名

    • .yml(主流)
    • .yaml
  • yaml语法规则

    • 大小写敏感

    • 属性层级关系使用多行描述,每行结尾使用冒号结束

    • 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用Tb键)

    • 属性值前面添加空格(属性名与属性值之间使用冒号+空格作为分隔)

    • #表示注释

    • 数组数据在书写位置的下方使用减号作为数据的开始,每行书写一个数据,减号与数据间空格分隔

  • yaml数据读取的方式

    数据如下:

    lesson: SpringBoot
    
    server:
    port: 80 person:
    name: mark
    age: 21
    tel: 123456789
    likes:
    - Java
    - Game
    - Music logging:
    level:
    root: info
    • 方式一:使用@value注解读取单个数据。引用方式:${一级属性名.二级属性名}

      @RestController
      @RequestMapping("/books")
      public class BookController {
      @Value("${lesson}")
      private String lesson;
      @Value("${server.port}")
      private Integer port;
      @Value("${person.likes[0]}")
      private String likes_00; @GetMapping("/{id}")
      public String getById(@PathVariable Integer id) {
      System.out.println(lesson);
      System.out.println(port);
      System.out.println(likes_00);
      return "hello Spring Boot";
      }
      }
    • 方式二:使用Environment对象加载所有环境信息并封装(一般在框架内部使用)

      @RestController
      @RequestMapping("/books")
      public class BookController {
      //加载所有的环境信息
      @Autowired
      private Environment environment; @GetMapping("/{id}")
      public String getById(@PathVariable Integer id) {
      System.out.println(environment.getProperty("lesson"));
      System.out.println(environment.getProperty("server.port"));
      System.out.println(environment.getProperty("person.likes[0]"));
      return "hello Spring Boot";
      }
      }
    • 方式三:自定义对象封装指定数据(常用)

      • 定义实体类,添加注解@Component@ConfigurationProperties

        @Getter
        @Setter
        @ToString
        //1.将其定义成一个bean使之能受Spring控制
        @Component
        //2.读取配置中的属性person
        @ConfigurationProperties(prefix = "person")
        public class Person {
        private String name;
        private Integer age;
        private String tel;
        private String[] likes;
        }
      • 使用时自动装配即可

        @RestController
        @RequestMapping("/books")
        public class BookController {
        @Autowired
        private Person person; @GetMapping("/{id}")
        public String getById(@PathVariable Integer id) {
        System.out.println(person);
        return "hello Spring Boot";
        }
        }
      • 自定义对象封装数据警告解决方案:添加以下依赖

        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
        </dependency>

5.8 多环境开发配置

yaml、yml配置方式:

#设置启用的环境
spring:
profiles:
active: dev ---
#开发
spring:
profiles: dev
server:
port: 80 ---
#生产
spring:
profiles: pro
server:
port: 81 ---
#测试
spring:
profiles: test
server:
port: 82

上述是过时写法,以下为不过时写法

#设置启用的环境
spring:
profiles:
active: dev ---
spring:
config:
activate:
on-profile: dev
server:
port: 82

properties配置方式:(了解即可)

在主启动配置文件application.properties中添加

#设置启用的环境
spring.profiles.active=dev

新建分类配置文件application-dev.properties添加环境配置

server.port=80

同理新建application-pro.properties、application-test.properties添加环境配置

server.port=81
server.port=82
  • 多环境启动命令格式

    • 因为有中文,所以先设置编码

    • 在打包前首先执行clean,然后package打包。避免影响结果

    • cmd执行:带参数启动SpringBoot

      java -jar SpringBoot_04_profile-0.0.1-SNAPSHOT.jar --spring.profiles.active=test

      即在测试环境下运行

    • 使用临时参数启动SpringBoot

      java -jar SpringBoot_04_profile-0.0.1-SNAPSHOT.jar --spring.profiles.active=test --server.port=88

  • 参数加载优先级:

    • 参考https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config
  • 多环境开发兼容问题(Maven与Boot)

    • Maven中设置生产环境

      <profiles>
      <profile>
      <id>dev</id>
      <properties>
      <profile.active>dev</profile.active>
      </properties>
      </profile> <profile>
      <id>pro</id>
      <properties>
      <profile.active>pro</profile.active>
      </properties>
      <activation>
      <activeByDefault>true</activeByDefault>
      </activation>
      </profile> <profile>
      <id>test</id>
      <properties>
      <profile.active>test</profile.active>
      </properties>
      </profile>
      </profiles>
    • Boot的yml中设置生产环境

      #设置启用的环境
      spring:
      profiles:
      active: ${profile.active} ---
      #开发
      spring:
      profiles: dev
      server:
      port: 80 ---
      #生产
      spring:
      profiles: pro
      server:
      port: 81 ---
      #测试
      spring:
      profiles: test
      server:
      port: 82
    • 打包运行发现端口号是8080

    • 解决:

      • 添加插件

        <!--对资源文件进行解析-->
        <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-resources-plugin</artifactId>
        <version>3.2.0</version>
        <configuration>
        <encoding>UTF-8</encoding>
        <useDefaultDelimiters>true</useDefaultDelimiters>
        </configuration>
        </plugin>

5.9 配置文件分类

  • SpringBoot中4级配置文件

    • 1级:file: config/application.yml ----最高
    • 2级:file: application.yml
    • 3级:classpath: config./application.yml
    • 4级:classpath: application.yml ----最低
  • 作用:
    • 1级与2级留做系统打包后设置通用属性(在资源管理器target目录下创建yml)
    • 3级与4级用于系统开发阶段设置通用属性(在IDEA的resources包下创建)

5.10 SpringBoot整合junit

Spring整合Junit

//设置运行器
@RunWith(SpringJUnit4ClassRunner.class)
//加载环境
@ContextConfiguration(classes = SpringConfig.class)
public class BookServiceTest { @Autowired
private BookService bookService; @Test
public void testGetById() {
Book book = bookService.getById(2);
System.out.println(book);
}
}

书写一个Service接口和实现类,直接在TestApplication中测试即可

@SpringBootTest
class SpringBoot07TestApplicationTests {
@Autowired
private BookService bookService; @Test
void contextLoads() {
bookService.save();
}
}

5.11 SpringBoot整合SSM

  • SpringBoot整合Spring(不存在)

  • SpringBoot整合SpringMVC(不存在)

  • SpringBoot整合MyBatis(主要、唯一)

    • 创建工程,在创建模块时添加MyBatis和MySQL

    • 书写实体类(pojo)和dao接口

    • 在dao接口上添加注解@Mapper

    • 修改配置文件,设置数据源参数

      spring:
      datasource:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql:///ssm_db
      username: root
      password: 123
      • 如果使用的SpringBoot版本低于2.4.3(不含),MySQL驱动版本大于8.0时,需要在url连接串中配置时区,或在MySQL数据库端配置时区解决此问题

        url: jdbc:mysql:///ssm_db?serverTimezone=UTC
    • 现在就可以运行啦

  • 如何使用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:///ssm_db
      username: root
      password: 123
      type: com.alibaba.druid.pool.DruidDataSource

5.12 基于SpringBoot的整合SSM案例

  • pom.xml

    配置起步依赖,必要的资源坐标(druid)

  • application.yml

    设置数据源、端口等

    #TODO 配置数据源相关信息
    server:
    port: 80 spring:
    datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db
    username: root
    password: 123
  • 配置类

    全部删除

  • dao

    设置@Mapper

  • 测试类

  • 页面

    • 将静态页面放在resources下的static目录下

    • 可以在static下创建index.html主页,这样不用输入地址即可进入

      <script>
      document.location.href="pages/books.html"
      </script>

6. MyBatisPlus

6.1 入门案例

MyBatisPlus(简称MP)是基于MyBatis框架基础上的增强型工具,旨在简化开发、提高效率

  • SpringBoot整合MyBatis开发过程

    • 创建SpringBoot工程
    • 勾选配置使用的技术
    • 设置dataSource相关属性(JDBC参数)
    • 定义数据层接口映射配置
  • 基于SpringBoot使用MyBatisPlus

    • 创建工程,勾选MySQL

    • 手动添加MyBatisPlus、Druid依赖

      <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.5.2</version>
      </dependency> <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.2.11</version>
      </dependency>
    • 配置数据源

      spring:
      datasource:
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/ssm_db
      username: root
      password: 123
    • 创建domain下的实体类User

      @Getter
      @Setter
      @ToString
      public class User {
      private Long id;
      private String name;
      private String password;
      private Integer age;
      private String tel;
      }
    • 创建dao下的接口UserDao继承BeanMapper,添加泛型为User

      @Mapper
      public interface UserDao extends BaseMapper<User> {
      }
    • 接下里就可以测试了

      @SpringBootTest
      class MyBatisPlus01QuickStartApplicationTests {
      @Autowired
      private UserDao userDao; @Test
      void testGetAll() {
      List<User> list = userDao.selectList(null);
      System.out.println(list);
      }
      }

6.2 MyBatisPlus简介

  • MyBatisPlus(简称MP)是基于MyBatis框架基础上的增强型工具,旨在简化开发、提高效率

  • 官网:https://mybatis.plus/ https://mp.baomidou.com

  • MyBatisPlus特性

    • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
    • 强大的 CRUD 操作:内置通用 Mapper、少量配置即可实现单表大部分 CRUD 操作
    • 支持 Lambda 形式调用:编写各类查询条件,无需再担心字段写错
    • 支持主键自动生成
    • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询

6.3 标准数据层CRUD功能

@SpringBootTest
class MyBatisPlus01QuickStartApplicationTests { @Autowired
private UserDao userDao; @Test
void testSave(){
User user = new User();
user.setName("王昭君");
user.setPassword("123");
user.setAge(12);
user.setTel("123456888");
userDao.insert(user);
} @Test
void testDelete(){
userDao.deleteById(1567537461138120705L);
} @Test
void testUpdate(){
User user = new User();
user.setId(1L);
user.setName("Tom666");
//提供哪些字段,修改哪些字段
userDao.updateById(user);
} @Test
void testById(){
User user = userDao.selectById(2L);
System.out.println(user);
} @Test
void testGetAll() {
List<User> list = userDao.selectList(null);
System.out.println(list);
} }

6.4 标准分页功能制作

@Test
void testGetByPage(){
//1:查第一页 2:一页有多少条数据
IPage page =new Page(1,2);
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());
//此时查数据发现查不出有多少页多少数据且数据为全部数据
//这就需要配置PM的分页拦截器
}

此时查数据发现查不出有多少页多少数据且数据为全部数据

这就需要配置PM的分页拦截器

@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mPlusInterceptor(){
//1.定义MP的拦截器
MybatisPlusInterceptor mybatisPlusInterceptor =new MybatisPlusInterceptor();
//2.在MP的拦截器添加具体的拦截器
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}

结果如下:

当前页码值:1
当前页有:2条
一共有:3页
一共有:5条数据
数据:[User(id=1, name=Tom666, password=tom, age=13, tel=18888888888), User(id=2, name=Jerry, password=jerry, age=12, tel=13999999999)]

可以在yml配置中开启日志

# 开启MP的日志(输出到控制台)
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

6.5 条件查询

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

由于输出日志太多,因此可以配置一个logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration> </configuration>

还可以清除MP和Spring的LOGO:在yml中配置banner

spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatisplus_db
username: root
password: 123
main:
banner-mode: off mybatis-plus:
global-config:
banner: false
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

这样输出结果就会很清爽

  • 方式一:

    @Test
    void testGetAll() {
    //按条件查询方式一:
    QueryWrapper wrapper = new QueryWrapper();
    //&lt:小于 &gt:大于
    wrapper.lt("age",18);
    List<User> userList = userDao.selectList(wrapper);
    System.out.println(userList);
    }
  • 方式二:

    //按条件查询方式二:
    QueryWrapper<User> wrapper = new QueryWrapper<User>();
    wrapper.lambda().lt(User::getAge,18);
    List<User> userList = userDao.selectList(wrapper);
    System.out.println(userList);
  • 方式三(推荐):

    //按条件查询方式三:
    LambdaQueryWrapper<User> lambdaQueryWrapper =new LambdaQueryWrapper<User>();
    lambdaQueryWrapper.lt(User::getAge,10);
    List<User> userList = userDao.selectList(lambdaQueryWrapper);
    System.out.println(userList);
    //方式三添加多个条件
    LambdaQueryWrapper<User> lambdaQueryWrapper =new LambdaQueryWrapper<User>();
    //lambdaQueryWrapper.lt(User::getAge,18);
    //lambdaQueryWrapper.gt(User::getAge,12);
    //12到18之间
    //lambdaQueryWrapper.lt(User::getAge,18).gt(User::getAge,12);
    //小于12或大于18
    lambdaQueryWrapper.lt(User::getAge,12).or().gt(User::getAge,18);
    List<User> userList = userDao.selectList(lambdaQueryWrapper);
    System.out.println(userList);

6.6 条件查询—null值处理

//模拟页面传递过来的查询数据
UserQuery userQuery = new UserQuery();
//userQuery.setAge(10);
userQuery.setAge2(30); LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>();
//先判定第一个参数是否为true,如果为true,如果为true连接当前条件
lambdaQueryWrapper.lt(null != userQuery.getAge2(),User::getAge,userQuery.getAge2());
lambdaQueryWrapper.gt(null != userQuery.getAge(),User::getAge,userQuery.getAge());
List<User> userList = userDao.selectList(lambdaQueryWrapper);
System.out.println(userList);

6.7 查询投影(查询的字段控制)

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>();
//该格式只适用于lambda表达式
lambdaQueryWrapper.select(User::getId, User::getName,User::getAge);
List<User> userList = userDao.selectList(lambdaQueryWrapper);
System.out.println(userList); /*结果:
Preparing: SELECT id,name,age FROM user
==> Parameters:
<== Columns: id, name, age
<== Row: 1, Tom666, 13
<== Row: 2, Jerry, 12
<== Row: 3, Mark, 21
<== Row: 4, 诸葛亮, 15
<== Row: 1567537209630830593, 王昭君, 12
<== Total: 5
*/

非lambda表达式写法:

QueryWrapper<User> lambdaQuery = new QueryWrapper<User>();
lambdaQuery.select("id","name","age");
List<User> userList = userDao.selectList(lambdaQuery);
System.out.println(userList);

查询总数

QueryWrapper<User> lambdaQuery = new QueryWrapper<User>();
lambdaQuery.select("count(*) as count");
List<Map<String, Object>> userMaps = userDao.selectMaps(lambdaQuery);
System.out.println(userMaps); /*结果:
==> Preparing: SELECT count(*) FROM user
==> Parameters:
<== Columns: count(*)
<== Row: 5
<== Total: 1
*/

分组统计

QueryWrapper<User> lambdaQuery = new QueryWrapper<User>();
//根据电话分组,查询个数
lambdaQuery.select("count(*) as count,tel");
lambdaQuery.groupBy("tel");
List<Map<String, Object>> userMaps = userDao.selectMaps(lambdaQuery);
System.out.println(userMaps);

6.8 查询条件

  • 范围匹配(>、=、between)

  • 模糊匹配(like)

  • 空判定(null)

  • 包含性匹配(in)

  • 分组(group)

  • 排序(order)

    用户登录

    LambdaQueryWrapper<User> lambdaQuery = new LambdaQueryWrapper<>();
    //等同于"="(equal)
    lambdaQuery.eq(User::getName, "Jerry").eq(User::getPassword, "jerry");
    User user = userDao.selectOne(lambdaQuery);
    System.out.println(user);

    购物设定价格区间、户籍设定年龄区间

    LambdaQueryWrapper<User> lambdaQuery = new LambdaQueryWrapper<>();
    //范围查询 lt le gt ge between
    //方式二
    //lambdaQuery.le(User::getAge,30).ge(User::getAge,10);
    //方式二
    lambdaQuery.between(User::getAge,10,30);
    List<User> list = userDao.selectList(lambdaQuery);
    System.out.println(list);

    查信息,搜索新闻(非全文检索版:like匹配)

    LambdaQueryWrapper<User> lambdaQuery = new LambdaQueryWrapper<>();
    //模糊匹配 Right和Left代表百分号的位置
    lambdaQuery.likeRight(User::getName,"M");
    List<User> list = userDao.selectList(lambdaQuery);
    System.out.println(list);

    统计报表(分组查询聚合函数)

    QueryWrapper<User> lambdaQuery = new QueryWrapper<User>();
    lambdaQuery.select("count(*) as count");
    List<Map<String, Object>> userMaps = userDao.selectMaps(lambdaQuery);
    System.out.println(userMaps);

    更多条件查询查看http://mybatis.plus/guide/wrapper.html#abstractwrapper

6.9 映射匹配兼容性

  • 问题一:表字段与编码属性设计不同步

    @Data
    public class User {
    @TableField(value = "pwd");
    private String password;
    }
  • 问题二:编码中添加了数据库中未定义的属性

    @Data
    public class User {
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;
    @TableField(exist = false)
    private boolean online;
    }
  • 问题三:采用默认查询开放了更多字段的查看权限

    @Data
    public class User {
    @TableField(value = "pwd",select = false);
    private String password;
    }
  • 问题四:表名与编码开发设计不同步

    @TableName("tbl_user")
    @Data
    public class User {
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;
    }

6.10 id生成策略

  • 不同的表应用不同的id生成策略

    • 日志:自增(1,2,3,4,…)
    • 购物订单:特殊规则(F023948AK3843)
    • 外卖单:关联地区日期等信息(1004202003143491)
    • 关系表:可省略id
    • ...
  • 注解:@TableId

  • 范例:

    @TableName("tbl_user")
    @Data
    public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    }
    • 相关属性:

      • value:设置数据库主键名称
      • type:设置主键属性的生成策略,值参照IdType枚举值
        • AUT0(0):使用数据库id自增策略控制id生成
        • NONE(1):不设置id生成策略
        • INPUT(2):用户手工输入id
        • ASSIGN ID(3):雪花算法生成id(可兼容数值型与字符串型)
        • ASSIGN UUID(4):以UUID生成算法作为id生成策略

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

@Test
void testDelete(){
List<Long> list = new ArrayList<>();
list.add(1567537209630830593L);
list.add(1568108502637993985L);
userDao.deleteBatchIds(list);
}
@Test
void testSelectPro(){
List<Long> list = new ArrayList<>();
list.add(1L);
list.add(3L);
list.add(4L);
userDao.selectBatchIds(list);
}

6.12 逻辑删除

  • 删除操作业务问题:业务数据从数据库张丢弃

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

    在数据库表中新增字段delete,类型为int,长度为1,默认值为0

    @TableLogic(value="0",deval = "1")

    在User类标注后,执行delete不会删除该条数据但是查询无法查到

    还可以在通用配置添加逻辑删除字段

    mybatis-plus:
    global-config:
    banner: false
    db-config:
    #逻辑删除字段
    logic-delete-field: deleted
    #删除
    logic-delete-value: 1
    #没有被删除
    logic-not-delete-value: 0

6.13 乐观锁

业务并发现象带来的问题:秒杀

  • 在数据库表中新增字段version,类型为int,长度为int最大长度11,默认值为1

  • 在User对象中添加属性version,添加注解@Version

  • 添加拦截器

    @Configuration
    public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mPlusInterceptor(){
    //添加乐观锁
    mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return mybatisPlusInterceptor;
    }
    }

6.14 代码生成器

  • 模板:MP提供

  • 数据库相关配置:读取数据库获取信息

  • 开发者自定义配置:手工配置

  • 使用步骤:

    • 添加坐标

      <!--代码生成器-->
      <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-generator</artifactId>
      <version>3.4.1</version>
      </dependency> <!--velocity模板引擎-->
      <dependency>
      <groupId>org.apache.velocity</groupId>
      <artifactId>velocity-engine-core</artifactId>
      <version>2.3</version>
      </dependency>
    • 代码生成器类Generator

      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:///mybatisplus_db?serverTimezone=UTC");
      dataSource.setUsername("root");
      dataSource.setPassword("123");
      autoGenerator.setDataSource(dataSource);
      autoGenerator.execute(); //设置全局配置
      GlobalConfig globalConfig = new GlobalConfig();
      //设置代码生成位置
      globalConfig.setOutputDir(System.getProperty("user.dir") + "/MyBatisPlus_04_generator/src/main/java");
      //设置生成完毕后是否打开生成代码所在的目录
      globalConfig.setOpen(false);
      //设置作者
      globalConfig.setAuthor("Mark");
      //设置是否覆盖原始生成的文件
      globalConfig.setFileOverride(true);
      //设置数据层接口名,%s为占位符,指代模块名称
      globalConfig.setMapperName("%sDao");
      //设置Id生成策略
      globalConfig.setIdType(IdType.ASSIGN_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");
      //设置数据库表的前缀名称,模块名 = 数据库表名 - 前缀名 例如: User = tbl_user - tbl_
      strategyConfig.setTablePrefix("tbl_");
      //设置是否启用Rest风格
      strategyConfig.setRestControllerStyle(true);
      //设置乐观锁字段名
      strategyConfig.setVersionFieldName("version");
      //设置逻辑删除字段名
      strategyConfig.setLogicDeleteFieldName("deleted");
      //设置是否启用lombok
      strategyConfig.setEntityLombokModel(true);
      autoGenerator.setStrategy(strategyConfig);
      //2.执行生成操作
      autoGenerator.execute();
      }
      }
  • 代码生成器模板

    • 添加坐标
    <dependencies>
    <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    </dependency>
    <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    </dependency>
    <dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    </dependency>
    <dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <optional>false</optional>
    </dependency>
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    </dependency>
    </dependencies>
    • 添加数据库配置和生成代码的位置
    dataSource.url=jdbc:mysql://123.456.789.000/tableName?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
    dataSource.driverName=com.mysql.cj.jdbc.Driver
    dataSource.username=root
    dataSource.password=9999
    package.base=com.mark.mall.modules
    • MyBatisPlusGenerator类
    public class MyBatisPlusGenerator {
    
    public static void main(String[] args) {
    String projectPath = System.getProperty("user.dir") + "/tuling-mpbg";
    String moduleName = scanner("模块名");
    String[] tableNames = scanner("表名,多个英文逗号分割").split(",");
    // 代码生成器
    AutoGenerator autoGenerator = new AutoGenerator();
    autoGenerator.setGlobalConfig(initGlobalConfig(projectPath));
    autoGenerator.setDataSource(initDataSourceConfig());
    autoGenerator.setPackageInfo(initPackageConfig(moduleName));
    autoGenerator.setCfg(initInjectionConfig(projectPath, moduleName));
    autoGenerator.setTemplate(initTemplateConfig()); //
    autoGenerator.setStrategy(initStrategyConfig(tableNames));
    autoGenerator.setTemplateEngine(new VelocityTemplateEngine());
    autoGenerator.execute();
    } /**
    * 读取控制台内容信息
    */
    private static String scanner(String tip) {
    Scanner scanner = new Scanner(System.in);
    System.out.println(("请输入" + tip + ":"));
    if (scanner.hasNext()) {
    String next = scanner.next();
    if (StrUtil.isNotEmpty(next)) {
    return next;
    }
    }
    throw new MybatisPlusException("请输入正确的" + tip + "!");
    } /**
    * 初始化全局配置
    */
    private static GlobalConfig initGlobalConfig(String projectPath) {
    GlobalConfig globalConfig = new GlobalConfig();
    globalConfig.setOutputDir(projectPath + "/src/main/java");
    globalConfig.setAuthor("XuShu");
    globalConfig.setOpen(false);
    globalConfig.setSwagger2(true);
    globalConfig.setBaseResultMap(true);
    globalConfig.setFileOverride(true);
    globalConfig.setDateType(DateType.ONLY_DATE);
    globalConfig.setEntityName("%s");
    globalConfig.setMapperName("%sMapper");
    globalConfig.setXmlName("%sMapper");
    globalConfig.setServiceName("%sService");
    globalConfig.setServiceImplName("%sServiceImpl");
    globalConfig.setControllerName("%sController");
    return globalConfig;
    } /**
    * 初始化数据源配置
    */
    private static DataSourceConfig initDataSourceConfig() {
    Props props = new Props("generator.properties");
    DataSourceConfig dataSourceConfig = new DataSourceConfig();
    dataSourceConfig.setUrl(props.getStr("dataSource.url"));
    dataSourceConfig.setDriverName(props.getStr("dataSource.driverName"));
    dataSourceConfig.setUsername(props.getStr("dataSource.username"));
    dataSourceConfig.setPassword(props.getStr("dataSource.password"));
    return dataSourceConfig;
    } /**
    * 初始化包配置
    */
    private static PackageConfig initPackageConfig(String moduleName) {
    Props props = new Props("generator.properties");
    PackageConfig packageConfig = new PackageConfig();
    packageConfig.setModuleName(moduleName);
    packageConfig.setParent(props.getStr("package.base"));
    packageConfig.setEntity("model");
    return packageConfig;
    } /**
    * 初始化模板配置
    */
    private static TemplateConfig initTemplateConfig() {
    TemplateConfig templateConfig = new TemplateConfig();
    //可以对controller、service、entity模板进行配置
    //mapper.xml模板需单独配置
    templateConfig.setXml(null);
    return templateConfig;
    } /**
    * 初始化策略配置
    */
    private static StrategyConfig initStrategyConfig(String[] tableNames) {
    StrategyConfig strategyConfig = new StrategyConfig();
    strategyConfig.setNaming(NamingStrategy.underline_to_camel);
    strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
    strategyConfig.setEntityLombokModel(true);
    strategyConfig.setRestControllerStyle(true);
    //当表名中带*号时可以启用通配符模式
    if (tableNames.length == 1 && tableNames[0].contains("*")) {
    String[] likeStr = tableNames[0].split("_");
    String likePrefix = likeStr[0] + "_";
    strategyConfig.setLikeTable(new LikeTable(likePrefix));
    } else {
    strategyConfig.setInclude(tableNames);
    }
    return strategyConfig;
    } /**
    * 初始化自定义配置
    */
    private static InjectionConfig initInjectionConfig(String projectPath, String moduleName) {
    // 自定义配置
    InjectionConfig injectionConfig = new InjectionConfig() {
    @Override
    public void initMap() {
    // 可用于自定义属性
    }
    };
    // 模板引擎是Velocity
    String templatePath = "/templates/mapper.xml.vm";
    // 自定义输出配置
    List<FileOutConfig> focList = new ArrayList<>();
    // 自定义配置会被优先输出
    focList.add(new FileOutConfig(templatePath) {
    @Override
    public String outputFile(TableInfo tableInfo) {
    // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
    return projectPath + "/src/main/resources/mapper/" + moduleName
    + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
    }
    });
    injectionConfig.setFileOutConfigList(focList);
    return injectionConfig;
    }
    }

SpringBoot&MyBatisPlus的更多相关文章

  1. spring-boot+mybatisPlus+shiro的集成demo 我用了5天

    spring-boot + mybatis-plus + shiro 的集成demo我用了五天 关于shiro框架,我还是从飞机哪里听来的,就连小贱都知道,可我母鸡啊.简单百度了下,结论很好上手,比s ...

  2. IDEA上创建 Maven SpringBoot+mybatisplus+thymeleaf 项目

    概述 在WEB领域,Java也是在不断的探索和改进,从开始的JSP--->Struts1--->Struts2+Spring--->Spring MVC--->SpringBo ...

  3. springboot+mybatisplus 测试代码生成

    测试springboot + mybatisplus 实现代码生成   使用默认的模板引擎 pom.xml文件 <?xml version="1.0" encoding=&q ...

  4. 2、SpringBoot+MybatisPlus整合-------BaseCRUD

    开发工具:STS 代码下载链接:GitHub管理代码 版本: Springboot:1.5.14.RELEASE 使用2.0以上的Springboot,会报出一些异常.欢迎知道异常原因的大牛解惑. M ...

  5. SpringBoot+MyBatisPlus整合时提示:Invalid bound statement(not found):**.dao.UserDao.queryById

    场景 在使用SpringBoot+MyBatisPlus搭建后台启动项目时,使用EasyCode自动生成代码. 在访问后台接口时提示: Invilid bound statement (not fou ...

  6. springboot+mybatisplus+sharding-jdbc分库分表实例

    项目实践 现在Java项目使用mybatis多一些,所以我也做了一个springboot+mybatisplus+sharding-jdbc分库分表项目例子分享给大家. 要是用的springboot+ ...

  7. springboot + mybatisPlus 入门实例 入门demo

    springboot + mybatisPlus 入门实例 入门demo 使用mybatisPlus的优势 集成mybatisplus后,简单的CRUD就不用写了,如果没有特别的sql,就可以不用ma ...

  8. 关于写SpringBoot+Mybatisplus+Shiro项目的经验分享四:部署到阿里云

    框架: SpringBoot+Mybatisplus+Shiro 简单介绍:关于写SpringBoot+Mybatisplus+Shiro项目的经验分享一:简单介绍 阿里云开放必要端口,mysql与t ...

  9. 关于写SpringBoot+Mybatisplus+Shiro项目的经验分享三:问题2

    框架: SpringBoot+Mybatisplus+Shiro 简单介绍:关于写SpringBoot+Mybatisplus+Shiro项目的经验分享一:简单介绍 搜索框是该项目重要的一环,由于涉及 ...

  10. 关于写SpringBoot+Mybatisplus+Shiro项目的经验分享二:问题1

    框架: SpringBoot+Mybatisplus+Shiro 简单介绍:关于写SpringBoot+Mybatisplus+Shiro项目的经验分享一:简单介绍 添加时,如果失败,不能正确跳转 c ...

随机推荐

  1. kubernetes之镜像拉取策略ImagePullSecrets;

    1.容器镜像是什么? 1.容器镜像(Container Image)是最终运行的软件: 2.容器镜像(最初为Docker镜像,现在叫OCI镜像更合适)是将软件打包的形式.但是容器镜像还可以携带额外的设 ...

  2. 一次客户需求引发的K8S网络探究

    前言 在本次案例中,我们的中台技术工程师遇到了来自客户提出的打破k8s产品功能限制的特殊需求,面对这个极具挑战的任务,攻城狮最终是否克服了重重困难,帮助客户完美实现了需求?且看本期K8S技术案例分享! ...

  3. 【manim】学习路径2-构建一些基础的图形,场景

    头文件引入 导入manim命名空间 from manim import * manim基本结构 这是一个最基本的manim结构,格式: from manim import * class 类的名字(S ...

  4. 高清地图转换(xord转apollo的bin文件)

    目标 将carla中的OpenDrive地图(carla\Unreal\CarlaUE4\Content\Carla\Maps\OpenDrive)转换为Apollo中可识别的地图格式(bin与txt ...

  5. KingbaseES例程之拥有大量索引的表导入数据

    概述 如何快速插入大量数据比如几千万上亿的带索引的数据表. 数据准备 准备一个拥有二十个索引的数据表. kingbase=# \d+ bigtab Table "kingbase.bigta ...

  6. KingbaseES R3 读写分离集群在线扩容案例

    案例说明: 1. 通过sys_basebackup创建新备库. 2. 将备库加入到Cluster nodes管理,可以用kingbase_monitor.sh一键启停. 3. 主备复制切换测试. 此次 ...

  7. 采云链SRM SaaS供应商管理系统,发展型中小企业的福音

    采购业务的发展遵循一些规律:采购从一开始围绕"供应商"开展,逐渐发展成围绕"货物"进行,如今围绕"供应商协同"和"采购流程管理&q ...

  8. 数论进阶&#160;

    数论进阶 扩展欧几里得算法 裴蜀定理(Bézout's identity) \(1\) :对于任意整数 \(a\),\(b\) ,存在一对整数 \(x\) ,\(y\) ,满足 \(ax+by=GCD ...

  9. parted创建磁盘分区并创建LVM(Linux合并多块大于2T的磁盘并合并到一个分区)

    文章转载自:https://blog.csdn.net/likemebee/article/details/85630808

  10. 第一个Django应用 - 第一部分:请求与响应

    一. 新建项目 进入你期望的项目保存目录,运行下面的命令: $ django-admin startproject mysite 这将在目录下生成一个mysite目录,也就是你的这个Django项目的 ...