Mybatis-plus入门级教程 -----干货学习篇

851 阅读7分钟

一.什么是mybatis-plus?

mybatis-plus就是mybatis的增强版,在mybatis的基础上只做增强,不做改变。对于一些单表简单的sql语句,我们几乎不用写任何代码,它的内部已经为我们封装好了,简单方便,非常适合用于快速开发。

1.1 mybatis-plus的特性

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

二.springboot项目集成mybatis-plus

2.1 初始化springboot项目,导入依赖

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <!--mybatis-plus-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.0.5</version>
    </dependency>
    <!--mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

注意:导入mp的依赖以后不要再引入mybatis和mybatis-spring!避免因为版本冲突导致的问题。

2.2 在application.properties中配置数据库的连接

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=convertToNull
spring.datasource.username=root
spring.datasource.password=123456

2.3 使用代码自动生成工具,一键生成代码(如下)

/**
* @author  lvjianyou
* @since   2020/3/15
*/
public class CodeGenerator {

   @Test
   public void run() {

       // 1、创建代码生成器
       AutoGenerator mpg = new AutoGenerator();

       // 2、全局配置
       GlobalConfig gc = new GlobalConfig();
       String projectPath = System.getProperty("user.dir");
        //*************需要修改的地方1 路径改为自己项目的实际路径  **********
       gc.setOutputDir("F:\\project\\cn\\hongyuan\\onlineedu_parent\\service\\service-cms" + "/src/main/java");   
       gc.setAuthor("吕建友");
       gc.setOpen(false); //生成后是否打开资源管理器
       gc.setFileOverride(false); //重新生成时文件是否覆盖
       gc.setServiceName("%sService");	//去掉Service接口的首字母I
       gc.setIdType(IdType.ID_WORKER_STR); //主键策略
       gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
       gc.setSwagger2(true);//开启Swagger2模式

       mpg.setGlobalConfig(gc);

       // 3、数据源配置
       DataSourceConfig dsc = new DataSourceConfig();
       //************ 需要修改的地方 2******************************************
       dsc.setUrl("jdbc:mysql://localhost:3306/onlineedu?serverTimezone=GMT%2B8");
       dsc.setDriverName("com.mysql.cj.jdbc.Driver");
       dsc.setUsername("root");
       dsc.setPassword("2556");
       dsc.setDbType(DbType.MYSQL);
       mpg.setDataSource(dsc);

       // 4、包配置
       PackageConfig pc = new PackageConfig();
        //************ 需要修改的地方 3 改为自己项目的实际名称******************************************
       pc.setModuleName("edu"); //模块名
       pc.setParent("com.ljy");  //包名
       pc.setController("controller");  //需要生成的名字
       pc.setEntity("entity");
       pc.setService("service");
       pc.setMapper("mapper");
       mpg.setPackageInfo(pc);

       // 5、策略配置
       StrategyConfig strategy = new StrategyConfig();
        //************ 需要修改的地方 4 ******************************************
       strategy.setInclude("crm_banner");      //要生成的表名称
       strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
       strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀

       strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
       strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
       strategy.setRestControllerStyle(true); //restful api风格控制器
       strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符

       mpg.setStrategy(strategy);


       // 6、执行
       mpg.execute();
   }
}

运行后即可以生成我们项目的全部代码,立即开始开发了!

2.4 MP的常用方法

  • select("first_conlum","second_conlum"): 选择查询出具体的某几列

  • eq("colums_name","select_name"): 查询出指定列名名称的数据。 ne() :

  • orderByDesc("conlum"): 按照指定的列根据降序排序

  • ge >= gt > le <= lt <

  • last(): 在sql语句的最后拼接一条语句。如lase("limit 8") 只查询8条语句

  • between("colums","begin","end"): 查询位于该区间内的值,也可查询字符串形式的时间 如:2019-2-03

2.5 注意

如果MP提供的方法不满足要求的话就需要自己手写sql语句,而且是使用maven构建项目,那么可能需要进行以下几个操作,不然maven默认不加载xml文件!

  1. 在pom.xml文件中添加配置
  <build>
        <!--编译项目中的xml文件-->
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>
  1. 在启动类上添加注解
@MapperScan("com.ljy.edu.mapper")   //你自己的mapper文件夹路径
  1. 在配置文件中添加配置
#配置项目的xml路径
mybatis-plus.mapper-locations=classpath:com/ljy/edu/mapper/xml/*.xml
做完这三步,应该就没问题了

三. MP特性介绍

3.1 主键策略

常见的主键策略有:1.自动增长策略。2.UUID 3.使用redis实现

3.1.1 MP自带策略(默认雪花算法,生成19位值)

MP支持的主键类型有很多:

主键策略.png

3.2 自动填充(往往是填充时间)

如果没有自动填充的话,在之前的项目中如果需要添加时间我们往往是自己new 一个时间添加进去,这样非常的不优雅,现在我们不需要自己new时间了!

3.2.1 在表中添加两个datetime类型的字段 create_time ,update_time

3.2.2 在实体类中的属性值上面添加注解

 @TableField(fill= FieldFill.INSERT)   //对应创建时间
 @TableField(fill = FieldFill.INSERT_UPDATE)   //对应修改时间

3.2.3 创建类,实现MetaObjectHandler,实现方法

代码如下:

@Component  //交给spring进行管理
public class MyMetaObjectHandler implements  MetaObjectHandler {
    //插入数据时进行填充
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("gmtCreate",new Date(),metaObject);
        this.setFieldValByName("gmtModified",new Date(),metaObject);
    }

    //修改数据时进行填充
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("gmtModified",new Date(),metaObject);
    }
}

以后我们就不用操心时间的问题了!

3.3 乐观锁 和 悲观锁 ( 针对于数据库操作的)

在并发(多个人同时)进行数据库操作时,很容易出现多个人同时操作一条数据,出现丢失更新(多个人操作一条数据,最后一个提交的数据把前一个人提交的数据覆盖掉)的问题,也就是脏读,幻读,不可重复读,这样肯定是不行的。

3.3.1 概念

乐观锁:乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回给用户错误的信息,让用户决定如何去做。乐观锁适用于读操作多的场景,这样可以提高程序的吞吐量。

悲观锁:当要对数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发。这种借助数据库锁机制,在修改数据之前先锁定,再修改的方式被称之为悲观并发控制【Pessimistic Concurrency Control,缩写“PCC”,又名“悲观锁”】。

3.3.2 MP实现乐观锁的方式

  1. 在表中添加字段 version,作为乐观锁的版本号
  2. 在实体类的属性上添加注解:@version
  3. 配置乐观锁插件
@Configuration
public class MpConfig {

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

这样,乐观锁的配置就完成了!

3.4 分页查询

3.4.1 配置类中配置分页插件

    @Bean
   public PaginationInterceptor paginationInterceptor() {
       return new PaginationInterceptor();
   }

代码使用:

        //创建分页对象
       Page<Teacher> teacherPage = new Page<>(current,limit);
       //调用page方法后会将对应的参数封装到teacherPage对象中
       
       QueryWrapper<Teacher> wrapper = new QueryWrapper<>();
       wrapper.orderByDesc("gmt_create");

       teacherService.page(teacherPage, wrapper);  //调用方法后会将查询出来的所有数据封装到teacherPage中,此时里面已经有所有数据了!

       long total = teacherPage.getTotal();   //获取总记录数
       .....

3.5 逻辑删除

传统的物理删除: 直接在数据库中删除数据,删除以后就再也找不回来了! 逻辑删除:在数据库中新增一个字段deleted,删除数据时并不是真正的删除,而是改变deleted状态的值!

3.5.1 在表中添加一个字段 deleted,类型为tingint即可

3.5.2 在实体类对应属性上添加注解 @TableLogic

3.5.3 配置逻辑删除插件

    @Bean
   public ISqlInjector iSqlInjector(){
       return new LogicSqlInjector();
   }


我们直接测试,就可以发现现在执行删除不是直接删除数据了,而是修改了deleted的值!

总结:这是我在学习路程上的收获,编程路漫漫,希望有感兴趣的小伙伴一起探讨,一起学习,一起进步!