Mybatis-Plus_mybatisplus dbtype_前度鸭的博客-程序员秘密

技术标签: mybatis  SSM框架  ssm  

概述

为什么要学习它呢?

MyBatisPlus可以节省我们大量工作时间,所有的CRUD代码它都可以自动化完成!

类似组件:JPA、 tk-mapper、MyBatisPlus

简介

官网: 简介 | MyBatis-Plus (baomidou.com) 简化 Mybatis开发

愿景

我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。

特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作,BaseMapper
  • 强大的 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

快速入门

地址: 快速开始 | MyBatis-Plus (baomidou.com)

步骤:

  1. 导入对应的依赖
  2. 研究依赖如何配置
  3. 代码如何编写?
  4. 提高扩展技术能力

步骤

  1. 创建数据库 mybatis_plus
  2. 创建user表
DROP TABLE IF EXISTS user;

CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT '主键ID',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);
-- 真实开发中, version(乐观锁),deleted(逻辑删除),gmt_create,gmt_modified

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');
  1. 初始化项目

    创建Spring Boot项目

  2. 添加依赖

        <!--Mybatis_Plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>

说明︰我们使用mybatis-plus 可以节省我们大量的代码,尽量不要同时导入mybatis和mybatis-plus ! 版本的差异!

  1. 连接数据库
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true*characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

##mysql8需要增加时区的配置   serverTimezone=GMT%2B8
  1. 传统方式pojo-dao(连接mybatis,配置mapper.xml文件 ) -service-controller

  2. 使用了mybatis_plus之后

  • pojo
public class User {
    

    //对应数据库中的主键(uuid、自增id、雪花算法、redis. zookeeper )
    private  Long id;
    private  String name;
    private  Integer age;
    private  String email;
	//有参构造 无参构造 set与get方法  toString()方法
}
  • mapper接口
// 在对应的mapper上面继承基本的类 BaseMapper
@Mapper
public interface UserMapper extends BaseMapper<User> {
      // 泛型

    //所有的CRUD操作都已经编写完成
    //不需要向以前的配置文件
}

//主类扫描接口
@MapperScan("com.qd.mybatis_plus.mapper")
  • 使用
@SpringBootTest
class MybatisPlusApplicationTests {
    

    //继承了Base Mapper,所有的方法都来自父类
    @Autowired
    private UserMapper userMapper;
    @Test
    void contextLoads() {
    
        //查询全部
        //参数是一个Wrapper,条件构造器
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
}

问题来了 ?

  1. SQL谁帮我们写的? MyBatis-Plus
  2. 方法哪里来的? MyBatis-Plus都写好了

配置日志

问题:我们所有的sql是不可见的,我们希望知道他是怎么执行的 ,我们必须要配置日志

## 配置日志   默认的控制台日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

CRUD扩展

Insert插入

    //测试插入
    @Test
    public void testInsert() {
    
        User user = new User();
        user.setName("前度");
        user.setAge(3);
        user.setEmail("[email protected]");

        int i = userMapper.insert(user);   //帮我们自动生成id
        System.out.println(i);   //受影响的行数  1
        System.out.println(user);
    }

数据库插入的id的默认值为:全局的唯一id

主键生成策略

默认 ID_WORKER 全局唯一id

参考文章: 分布式系统唯一ID生成方案汇总 - nick hao - 博客园 (cnblogs.com)

雪花算法:

​ snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心:北京,上海等,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯一!

主键自增 配置

  1. 在实体类字段上添加@TableId(type = IdType.AUTO)
  2. 数据库字段要为自增!
  3. 再次测试即可

其余的源码解释

public enum IdType {
    
    AUTO(0),     //数据库id自增
    NONE(1),   //未设置主键  必须自己配置id
    INPUT(2),    //手段输入
    ID_WORKER(3),   //默认的全局唯一id
    UUID(4),   //全局唯一id  uuid
    ID_WORKER_STR(5);  // ID_WORKER的字符串表示法
}

更新操作

    //测试更新
    public  void  testUpdate(){
    

        User user = new User();
        user.setName("前度666");
        user.setAge(3);
        user.setEmail("[email protected]");
        //updateById 但是参数是一个对象!
        //可以通过条件拼接动态sql
        userMapper.updateById(user);
    }

所有的sql都是自动帮你动态配置的!

自动填充

创建时间、修改时间!这些个操作一遍都是自动化完成的,我们不希望手动更新!

阿里巴巴开发手册∶所有的数据库表: gmt_creategmt_modified所有表必备 需要自动化

方法一:数据库级别 (不建议使用)

  1. 在表中新增字段 create_time, update_time

在这里插入图片描述

  1. 同步实体类
    private Data createTime;
    private Data updateTime;
  1. 更新查看即可

方法二: 代码级别

  1. 删除数据库的默认值,更新操作

在这里插入图片描述

  1. 在实体类字段属性增加注解
    //字段添加填充内容
    @TableField(fill = FieldFill.INSERT)  //查询
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE) //查询与更新
    private Date updateTime;
  1. 编写处理器处理注解即可

    官网地址: 自动填充功能 | MyBatis-Plus (baomidou.com)

  • 添加 handler包 含有 MyMetaObjectHandler类 去实现 MetaObjectHandler
  • @Component //一定不要忘记把处理器注册到IOC容器中!!
@Component   //一定不要忘记把处理器注册到IOC容器中!!!
public class MyMetaObjectHandler implements MetaObjectHandler {
    

    private final static Date DATE_TIME = new Date();

    //插入时候填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
    

        //setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject) {
    
        this.setFieldValByName("createTime", DATE_TIME, metaObject);
        this.setFieldValByName("updateTime", DATE_TIME, metaObject);
    }

    //更新时候填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
    
        this.setFieldValByName("updateTime", DATE_TIME, metaObject);
    }
}

4 .测试

在这里插入图片描述

乐观锁处理

乐观锁 : 十分乐观,它总是认为不会出现问题,无论干什么不去上锁 ! 如果出现了问题,再次更新值测

悲观锁 :十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!

version、new version

当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败
-- 乐观锁 : 1 先查询,获得版本号 version = 1

-- A线程
update user set name = "前度" , version = version + 1
where id = 2 and version = 1 ;

-- B线程 抢先完成,这个时候版本号被修改  version = 2
update user set name = "前度" , version = version + 1
where id = 2 and version = 1 ;

测试

乐观锁插件: 乐观锁 | MyBatis-Plus (baomidou.com)

  1. 给数据库增加 version 字段

在这里插入图片描述

  1. 实体类加对应的字段
    @Version   //乐观锁 Version注解
    private  Integer version;
  1. 注册组件

    添加 config包 含有 MyBatisPlusConfig

@MapperScan("com.qd.mybatis_plus.mapper")  //扫描
@EnableTransactionManagement   //开启事务
@Configuration //配置类
public class MyBatisPlusConfig {
    

    //注册乐观锁插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
    
        return new OptimisticLockerInterceptor();
    }
}
  1. 测试
    //测试乐观锁插件  成功
    @Test
    public void testOptimisticLockerInterceptor1() {
    
        //查询用户修改
        User user = userMapper.selectById(1L);
        //修改用户信息
        user.setAge(20);
        //执行更新
        userMapper.updateById(user);
    }

	//----------------------------------------------------------

    //测试乐观锁插件  失败   多线程下
    @Test
    public void testOptimisticLockerInterceptor2() {
    
        //线程1
        User user = userMapper.selectById(1L);
        user.setAge(21);

        //模拟另外一个线程执行插队操作
        User user2 = userMapper.selectById(1L);
        user2.setAge(22);
        userMapper.updateById(user2);

        //可以使用自旋锁多次尝试提交
        userMapper.updateById(user);  //如果没有乐观锁,就会覆盖插队线程的值  
    }  

	//结果仍为22

在这里插入图片描述

查询操作

    //测试查询
    @Test
    public void testSelectById() {
    
        User user = userMapper.selectById(1L);
        System.out.println(user);

    }

    //测试批量查询
    @Test
    public void testSelectById02() {
    
        List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
        users.forEach(System.out::println);
    }

    //测试条件之一查询 map操作
    @Test
    public void testSelectById03() {
    
        HashMap<String, Object> map = new HashMap<>();
        //自定义查询
        map.put("name", "前度");
        map.put("age", 18);   //多个条件
        List<User> users = userMapper.selectByMap(map);
        users.forEach(System.out::println);
    }

分页查询

分页在网站这一块可太重要了,实现分页的方法有:

  • 原始的 limit 进行分页
  • 用 pageHelper 第三方插件分页
  • MybatisPlus 已经内置分页插件

如何使用分页插件呢?

官网: 分页 | MyBatis-Plus (baomidou.com)

  1. 配置拦截器组件
 	//分页插件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
    
        return new PaginationInterceptor();
    }
  1. 直接使用 page 对象即可
    //测试分页查询
    @Test
    public void testPage() {
    
        //参数一: 当前页
        //参数二: 页面大小
        //使用了分页插件之后,分页操作非常简单
        Page<User> page = new Page<>(2, 5); //第1页 每页5条
        userMapper.selectPage(page, null);
        page.getRecords().forEach(System.out::println);
        page.getTotal();//获得总数
    }

在这里插入图片描述

删除操作

  • 根据 id 删除记录
    //测试删除
    @Test
    public void testDeleteById() {
    
        userMapper.deleteById(1402192921201025026L);
    }
    
    //测试通过id批量删除
    @Test
    public void testDeleteById02() {
    
        userMapper.deleteBatchIds(Arrays.asList(1L, 2L, 3L));
    }

    //测试通过map条件删除
    @Test
    public void testDeleteById03() {
    
        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "前端");
        userMapper.deleteByMap(map);
    }

我们在工作中会遇到一些问题; 逻辑删除

逻辑删除

物理删除 : 从数据库中直接移除

逻辑删除 : 在数据库中没有移除,而是通过一个变量来让他失效 ! deleted=0 => deleted=1

管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!

测试

  1. 在数据表中增加 deleted字段

在这里插入图片描述

  1. 实体类中增加属性
    @TableLogic //逻辑删除
    private Integer deleted;
  1. 配置逻辑删除组件

    官网: 逻辑删除 | MyBatis-Plus (baomidou.com)

    //逻辑删除组件
    @Bean
    public ISqlInjector sqlInjector() {
    
        return new LogicSqlInjector();
    }

//注意:高版本无需配置组件 直接下一步即可
  1. 配置 yaml
##配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
  1. 测试
    //测试删除
    @Test
    public void testDeleteById() {
    
        userMapper.deleteById(1402192921201025026L);
    }

在这里插入图片描述

可以发现,数据仍在数据库中 并且在查询中会字段拼接该参数 查询不到逻辑删除的字段


PS:以上CRUD操作及其扩展,必须精通,会大大提高效率

多表操作

这里不作过多配置 xml 的使用 请前往下面两篇博客学习

  1. mybatis plus 一对多,多表联查的使用小记 - 黑化肥会挥发吗 - 博客园 (cnblogs.com)

  2. mybatis-plus配置xml进行多表查询 - 简书 (jianshu.com)

条件构造器

wrapper 十分重要 我们写一些复杂的sql就可以使用它来替代!

官网: 条件构造器 | MyBatis-Plus (baomidou.com)

  • 测试一
	@Test
    public void contextLoads() {
    

        //查询name不为空 并且邮箱不为空  年龄大于等于3岁的用户
        QueryWrapper<User> Wrapper = new QueryWrapper<>();
        Wrapper.isNotNull("name")
                .isNotNull("email")
                .ge("age", 20);  //大于等于
        userMapper.selectList(Wrapper).forEach(System.out::println);
    }
  • 测试二
    @Test
    public void contextLoads02() {
    

        //查询name为前度
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("name", "前度");
        System.out.println(userMapper.selectOne(wrapper));  //查询一个  查询多个用list,map
    }
  • 测试三
  @Test
    public void contextLoads03() {
    

        //查询年龄在20到30之间的用户
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("age", 20, 30);  //区间
        Integer count = userMapper.selectCount(wrapper);  //查询结果数
        System.out.println(count);
        List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
        maps.forEach(System.out::println);
    }
  • 测试四
    @Test
    public void contextLoads04() {
    

        //子查询
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.inSql("id", "select id from user where id<3");
        List<Object> objects = userMapper.selectObjs(wrapper);
        objects.forEach(System.out::println);
    }
  • 测试五
    @Test
    public void contextLoads05() {
    

        //通过id进行排序
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

更多使用方法直接查看官方文档即可

代码字段生成器

run前开启MySQL 服务!!! 有些配置需要具体更改建议写在 test


import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.ArrayList;
import java.util.List;

public class AutoGenerateTest {
    
    public static void main(String[] args) {
    
        // 创建generator对象
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir"); // 项目根目录不可修改
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("qiandu");  // 作者信息
        gc.setOpen(false);  // 打开文件夹
        gc.setFileOverride(false);// 是否覆盖
        gc.setServiceName("%sService"); // Service层接口 去前缀
        gc.setIdType(IdType.AUTO);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setSwagger2(false);  // 设置Swagger2文档
        mpg.setGlobalConfig(gc);

        // 设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setDbType(DbType.MYSQL);  // 枚举类型 选择数据库
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        dsc.setUrl("jdbc:mysql://localhost:3306/ssmdb?serverTimezone=Asia/Shanghai");
        // jdbc:mysql://localhost:3306/数据库名称?serverTimezone=Asia/Shanghai
        mpg.setDataSource(dsc);

        // 设置包信息
        PackageConfig pc = new PackageConfig();
        pc.setParent("com.qd");  //包
        pc.setEntity("pojo");
        pc.setMapper("mapper");
        pc.setService("service");
        pc.setServiceImpl("service.impl");
        pc.setController("controller");
        mpg.setPackageInfo(pc);

        // 修改*mapper.xml文件
        // 注入自定义配置,可以在 VM 中使用 cfg.abc 【可无】
        InjectionConfig cfg = new InjectionConfig() {
    
            @Override
            public void initMap() {
    
            }
        };
        List<FileOutConfig> focList = new ArrayList<>();
        focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
    
            @Override
            public String outputFile(TableInfo tableInfo) {
    
                // 生成模块化mapper文件
                return projectPath + "/src/main/resources/mapper/" + tableInfo.getEntityName() + "/" +
                        tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 策略配置 与数据库相关
        StrategyConfig strategyConfig = new StrategyConfig();
        strategyConfig.setInclude("tb_goods");  // 表名 改!!!
        strategyConfig.setTablePrefix("tb_"); // 去除表前缀tb_
        strategyConfig.setNaming(NamingStrategy.underline_to_camel); // 表名映射实体类
        strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel); // 字段映射实体类
        strategyConfig.setEntityLombokModel(true); // 加载Lombok
        strategyConfig.setLogicDeleteFieldName("deleted"); // 逻辑删除  具体看情况!
        // 自动填配置
        TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
        TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(gmtCreate);
        tableFills.add(gmtModified);
        strategyConfig.setTableFillList(tableFills);
        // 乐观锁配置
        strategyConfig.setVersionFieldName("version");
        // 设置controller
        strategyConfig.setRestControllerStyle(true); // restful风格
        strategyConfig.setRestControllerStyle(true); // 下划线命名
        mpg.setStrategy(strategyConfig);
        // 运行
        mpg.execute();
        System.out.println("====================【 PS:将会在mapper层与资源目录共同生成mapper文件,请保留合适的文件!!!】====================");
    }
}

配置类集合

import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@MapperScan("com.qd.mybatis_plus.mapper")  //扫描
@EnableTransactionManagement   //开启事务
@Configuration //配置类
public class MyBatisConfig {
    

    //注册乐观锁插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
    
        return new OptimisticLockerInterceptor();
    }

    //分页组件
    @Bean
    public PaginationInterceptor paginationInterceptor() {
    
        return new PaginationInterceptor();
    }

    //逻辑删除组件
    @Bean
    public ISqlInjector sqlInjector() {
    
        return new LogicSqlInjector();
    }
}

整合SpringBoot项目

1、导包

<!--freemarker模板引擎-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

<!--mysql数据库驱动-->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.26</version>
</dependency>

<!--c3p0  druid连接池-->
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>

<!--mybatis-plus依赖-->
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <version>3.4.2</version>
</dependency>

<!--mybatis-plus代码生成器-->
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-generator</artifactId>
  <version>3.4.1</version>
</dependency>
<dependency>
  <groupId>org.apache.velocity</groupId>
  <artifactId>velocity-engine-core</artifactId>
  <version>2.0</version>
</dependency>

<!--web依赖-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!--lombok依赖-->
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <optional>true</optional>
  <version>1.18.20</version>
</dependency>

<!--测试test依赖-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>

<!--导入aop-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

构建排除

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build><build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                        <exclude>
                            <groupId>com.baomidou</groupId>
                            <artifactId>mybatis-plus-generator</artifactId>
                        </exclude>
                        <exclude>
                            <groupId>org.apache.velocity</groupId>
                            <artifactId>velocity-engine-core</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qd2013498006/article/details/117739892

智能推荐

最近总结的Android笔记(三)_cat system font_scale_mockingbirds的博客-程序员秘密

android系统增加framework服务在 frameworks/base/core/java/android/os目录中增加对应的aidl文件在frameworks/base/Android.mk文件中增加定义的aidl文件 LOCAL_SRC_FILES +=mmm frameworks/base 此时会自动根据aidl文件生成对应的stub接口在frameworks/base/

Spring注解validated_那些年的代码的博客-程序员秘密

spring-boot中可以用@validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理。比如,我们判断一个输入参数是否合法,可以用如下方式一 基础使用因为spring-boot已经引入了基础包,所以直接使用就可以了1 首先在controller上声明需要对数据进行校验@RequestMapping(value="/url.json",method= {R...

洛谷 P5734 【深基6.例6】文字处理软件 题解 两种方法 (字符串 C/C++)_怎么用c语言解决洛谷文字处理软件问题_【止心】的博客-程序员秘密

方法一:大部分手动实现//P5734 【深基6.例6】文字处理软件//#define LOCAL#include &lt;iostream&gt;#include &lt;cstdio&gt;#include &lt;cstring&gt;#include &lt;cmath&gt;#include &lt;algorithm&gt;#include &lt;cctype&gt;#define inf 0x3f3f3f3f#define eps 1e-6using namespac.

“羊吃草”论数据隐私保护难题破解之道? 世界第一本联邦学习专著问世_FedAI Ecosystem的博客-程序员秘密

看到这本书的封面插画,你是否以为即将面对一本童话故事书?实际上,这本书“意义重大”,绝非童话,是用“羊吃草”的比喻给我们解释:大数据时代,人工智能在隐私安全前提下实现数据合作的最优解决方案。这就是世界上第一本“联邦学习”专著——《Federated Learning》(英文版)/《联邦学习》(中文版),由微众银行首席人工智能官杨强教授及人工智能部刘洋、程勇、康焱、陈天健、于涵等多位人工智能领域顶级专家历时两年,共同编撰而成。2019年12月,《Federated Learning》由美国Morgan

水平居中和垂直居中css_如何使用CSS将图像垂直和水平居中_cumian9828的博客-程序员秘密

水平居中和垂直居中cssThere are many ways to align HTML elements with CSS. One of the most common things developers struggle with is trying to center an element in the middle of the page. 有许多方法可以将HTML元素与CSS对齐。 ...

Python连接MySQLdb的mach-o, but wrong architecture错误解决_adwfcu的博客-程序员秘密

错误提示1/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/MySQL_python-1.2.3-py2.6-macosx-10.6-x86_64.egg/_mysql.so: mach-o, but wrong architecture

随便推点

Python图像识别之图片相似度计算!强的一批!_python 计算图像相似度_PythonJavaPHP的博客-程序员秘密

1.背景要识别两张图片是否相似,首先我们可能会区分这两张图是人物照,还是风景照等......对应的风景照是蓝天还是大海......做一系列的分类。从机器学习的的角度来说,首先要提取图片的特征,将这些特征进行分类处理,训练并建立模型,然后在进行识别。但是让计算机去区分这些图片分别是哪一类是很不容易的,不过计算机可以知道图像的像素值的,因此,在图像识别过程中,通过颜色特征来识别是相似图片是...

(染色归一化)病理图像(HE或者WSI)图像标准化方法小介绍_杰青的垫脚石的博客-程序员秘密

虽说是CSDN,但因为处理的过程中要用到病理图片,所以这里简单的介绍一下病理图像的标准化。首先介绍一下我们的病理图像。病理图像就是我们高中时候用的玻片在扫描仪下拍摄的高分辨率图像。具体制作过程可以参见百度。https://wenku.baidu.com/view/60b5d0fe2af90242a995e58a.html病理图像可以帮助医生对病人做出诊断。通过病理图像,我们可以看到肿瘤细胞的.....................

微信公众号【客服接口】_微信公众号客服接口_风神修罗使的博客-程序员秘密

人生最低的境界是平凡,其次是超凡脱俗,最高是返璞归真的平凡。Kf_account.cs代码: public partial class Kf_account : Form { private readonly DataTable adt_user = new DataTable(); private readonly string as_INIFile =

18.Spring Boot 2.x 最佳实践之 Java Mail Sender集成_技术宅星云的博客-程序员秘密

这篇博文来讲解Spring Boot 和邮件发送集成的示例。

Sharepoint客户端对象模型上传附件_deju1282的博客-程序员秘密

Sharepoint2010中引入了客户端对象模型(COM) 来加强外部对sharepoint站点信息的访问(sharepoint2007只能通过web service)SharePoint中有3种客户端对象模型:ECMAScript.NET托管客户端对象模型Silverlight客户端对象模型3种客户端对象模型都通过Client.svc来实现与服务器的交互,...