Mybatis-plus学习(基于版本3.0.5)
创始人
2024-01-13 00:42:06

文章目录

  • 一.概念
    • 1.1 简介
    • 1.2 特性
  • 二.快速入门
  • 三.CRUD扩展
    • 3.1 Insert插入
    • 3.2 主键生成策略
    • 3.3 Update更新
    • 3.4 自动填充
    • 3.5 乐观锁
    • 3.6 查询操作
    • 3.7 删除操作
    • 3.8 性能分析插件(新版本的Mybatis-plus已将此插件移除)
    • 3.9 条件构造器
    • 3.10 代码生成器

一.概念

1.1 简介

Mybatisplus从字面上面理解时Mybatis的加强版,它可以大大节省我们大量的工作时间,所有的增删改查代码它都可以在mybatisplus中自动的完成,其本质上上Mybatis的一个增强工具,在Mybatis的基础上只做增强不做改变,为简化开发,提高效率而生。
在这里插入图片描述

1.2 特性

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

二.快速入门

使用官方提供的快速开始文档

  1. 创建数据库mybatisplus
  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)
);
DELETE FROM user;INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
  1. 创建一个springboot项目
  2. 导入依赖
mysqlmysql-connector-java
org.projectlomboklombok
com.baomidoumybatis-plus-boot-starter3.3.1.tmp
  1. 连接数据库
  • 配置SpringBoot配置文件
spring:datasource:username: rootpassword: 123456url: jdbc:mysql://localhost:3306/mybatisplus?userSSL=false&useUnicode=true&characterEncoding=utf-8driver-class-name: com.mysql.cj.jdbc.Driver
  1. 编写pojo类(与传统使用Mybatis一样)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class user {private Long id;private String name;private Integer age;private String email;
}
  1. 配置Dao层

使用mybatisplus之后只需要在对应的mapper上面继承基本的类BaseMapper即可(不需要像Mybatis那样繁琐)。到此所有的CRUD已经Mybatisplus帮我们自动编写完成十分方便(当然我们也可以在这里面定义自己的代码)。

@Repository //代表这个接口是Dao层的
public interface UserMapper extends BaseMapper {
}
  • 在启动类上配置mapper扫描(此时dao层就配置完毕了)
@MapperScan("com.chailong.getspring.mapper")  //扫描mapper的文件夹
@SpringBootApplication
public class GetspringApplication {public static void main(String[] args) {SpringApplication.run(GetspringApplication.class, args);}
  • 在测试类中测试
@SpringBootTest
class GetspringApplicationTests {@Autowiredprivate UserMapper userMapper; //注入usermapper的bean@Testvoid contextLoads() {//seleclist的参数是一个wrapper(条件构造器)List userList=userMapper.selectList(null);//查询全部for (user user1 : userList) {System.out.println(user1);}}
}

运行结果:
在这里插入图片描述
8. 配置日志

在前面的操作过程中我们是具体看不到我们的sql语句的,为了能在控制台看到我们的sql语句,我们需要对日志进行配置

mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

结果:
在这里插入图片描述

三.CRUD扩展

3.1 Insert插入

  1. 编写插入代码
   @Testvoid testInsert() {user usernew=new user();usernew.setName("chailong");usernew.setAge(11);usernew.setEmail("2012126846@qq.com");int result=userMapper.insert(usernew);System.out.println(result);}

结果:(发现自动插入了id)
在这里插入图片描述
2. 问题

思考这里为什么会自动生成唯一ID?
这就要涉及到分布式系统唯一id生成中的雪花算法

3.2 主键生成策略

  1. 雪花算法

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

  1. 使用@TableId注解可以配置主键生成策略(下面是常见的策略)

默认策略是ID_WORKER全局唯一ID

@Data
@AllArgsConstructor
@NoArgsConstructor
public class user {@TableId(type = IdType.ID_WORKER )private Long id;private String name;private Integer age;private String email;
}

在这里插入图片描述
3. 主键自增策略

  1. 在实体类字段上配置@TableId(type=IdType.AUTO)
  2. 勾选Mysql数据库中ID自增选项
  1. 其它自增策略源码解释
public enum IdType {AUTO(0), //数据库id自增NONE(1),//未设置主键INPUT(2),//手动输入(数据库里面自己填)ID_WORKER(3),//默认全局唯一idUUID(4),//全局唯一idID_WORKER_STR(5);//ID_worker的字符串表示法
}

3.3 Update更新

测试类代码

   @Testvoid testUpdate() {user usernew=new user();usernew.setId(11);usernew.setName("jakiechai");usernew.setAge(11);usernew.setEmail("2012126846@qq.com");int i=userMapper.updateById(usernew);System.out.println(i);}

结果:
在这里插入图片描述
可以发现mybatis-plus帮我们实现了自动动态配置,这就需要讲到mybatis-plus的自动填充技术,下面介绍自动填充技术。

3.4 自动填充

问题提出:在创建数据表中我们有些参数是不希望用户去手动填充的而是希望系统帮我们去自动填充(如表创建时间和表修改时间等)。阿里巴巴开发手册规定几乎所有数据表字段都必须要有一个gmt_create(创建时间)和gmt_modified(修改时间),而这两个参数是需要系统自动填充的;这就涉及到了自动填充技术。

  1. 数据库级别自动填充(实际生活中不建议这种方法)

在表中新增字段创建时间和修改时间设置默认值即可(修改表字段即可,注意pojo对应属性也要更改)

  1. 代码级别自动填充
  1. 删除数据库默认值

在这里插入图片描述

  1. 实体类属性上加入相关注解
    在TableField接口中有一个fill函数用于属性值的自动填充
    FieldFill fill() default FieldFill.DEFAULT;
    FieldFill的值表示填充的方法

public enum FieldFill {DEFAULT,  //默认不填充INSERT,   //插入时填充UPDATE,   //更新时填充INSERT_UPDATE; //更新或插入时填充}

然后在类属性上加入@TableField注解

@Data
@AllArgsConstructor
@NoArgsConstructor
public class user {@TableId(type = IdType.AUTO )private int id;private String name;private Integer age;private String email;@TableField(fill = FieldFill.INSERT_UPDATE)private Date createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;
}
  1. 编写处理器来处理注解
  1. 在主目录下建立一个Handler包,专门用来放SpringBoot项目的处理器,编写处理器代码
@Slf4j  //使用日志
@Component  //处理器加入到ioc容器中
public class MyMetaObjectHandler implements MetaObjectHandler {//实现插入时自动填充@Overridepublic void insertFill(MetaObject metaObject) {log.info("start insert fill.....");//setFieldValByName(字段名,字段值,metaObject)this.setFieldValByName("createTime",new Date(),metaObject);this.setFieldValByName("updateTime",new Date(),metaObject);log.info("insert over");}//实现更新时自动填充@Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill.....");//setFieldValByName(字段名,字段值,metaObject)this.setFieldValByName("createTime",new Date(),metaObject);this.setFieldValByName("updateTime",new Date(),metaObject);log.info("update over");}
}
  1. 测试类代码
    @Testvoid testInsert() {user usernew=new user();usernew.setName("menglei");usernew.setAge(11);usernew.setEmail("2012126846@qq.com");int result=userMapper.insert(usernew);System.out.println(result);}

运行结果:数据库插入成功(字段也帮我们自动填充了)
在这里插入图片描述

3.5 乐观锁

  1. 简介

所谓的乐观锁,其实主要就是一种思想,因为乐观锁的操作过程中其实没有没有任何锁的参与,乐观锁只是和悲观锁相对,严格的说乐观锁不能称之为锁。所以要了解乐观锁的概念,通常与悲观锁对比起来看才更好理解,下面我们就通过乐观锁与悲观锁的对比来更好的理解乐观锁。乐观锁总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,只在更新的时候会判断一下在此期间别人有没有去更新这个数据。悲观锁总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞,直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。

  1. 乐观锁实现方式
  1. 取出记录时获取当前version
  2. 更新时带上这个version
  3. 执行更新时,set version=nerVersion where version =oldVersion
  4. 如果version不对,就更新失败
  1. 举例说明
    假设两个线程A和B都在执行更新操作:
//A执行更新update user set name="kuanshen",version=version+1where id=2 and version =1
//B执行更新update user set name="kuanshen",version=version+1where id=2 and version =1

假设B先完成了更新,version被改变,此时A就会更新失败,这就是乐观锁实现线程安全的机制
4. 使用Mybatis-plus的乐观锁插件

  1. 给数据表中加入version字段,并设置默认值为1

在这里插入图片描述

  1. 实体类同步,并给属性上加入乐观锁注解

在这里插入图片描述

  1. 在Handler文件下编写乐观锁的组件
@Configuration   //声明这是一个配置类
@EnableTransactionManagement  //事务
public class MybatisplusConfig {//注册乐观锁插件@Beanpublic OptimisticLockerInterceptor optimisticLockerInterceptor() {return new OptimisticLockerInterceptor();}}
  1. 测试乐观锁
  • 单线程情况
    @Testvoid testOptimisticLocker(){//1查询用户信息user usermy=userMapper.selectById(1);//2.修改用户信息usermy.setName("mike");usermy.setAge(11);usermy.setEmail("jake.com");//3.更新用户信息userMapper.updateById(usermy);}

运行结果:更新成功version加1(单线程不存在现场安全问题,一定会更新成功)
在这里插入图片描述

  • 多线程情况模拟
 @Testvoid testOptimisticLocker(){//线程1(准备更新但是还没更新)user usermy=userMapper.selectById(1);usermy.setName("mike2");usermy.setAge(11);usermy.setEmail("jake.com");//线程2(插队在线程1之前执行了更新)user usermy2=userMapper.selectById(1);usermy2.setName("mike1");usermy2.setAge(11);usermy2.setEmail("mary.com");userMapper.updateById(usermy2);//线程2的更新操作userMapper.updateById(usermy);//线程1的更新操作(如果没有乐观锁就会把线程2更新的值直接覆盖掉)}

结果:乐观锁机制使得线程1没有更新
在这里插入图片描述

3.6 查询操作

  1. 根据Mybatis-plus提供的接口直接用即可(比如下面根据ID查询多个用户)
  @Testvoid testquery(){System.out.println(userMapper.selectBatchIds(Arrays.asList(1,2,3)));}

结果:
在这里插入图片描述
2. 分页查询

在以前的ssm项目中几乎使用的都是原始的limit分页方式或者使用pageHelper等第三方插件,Mybaits-plus也为开发者准备了分页插件,开发直接使用即可,十分方便

  1. 配置分页组件(在配置类中加入分页的Bean就行)
  @Beanpublic PaginationInterceptor pageInationInterceptor(){return new PaginationInterceptor();}
  1. 使用Page对象进行分页
   @Testvoid testPage(){Page page=new Page<>(2,5);//当前页第2页,每页5条数据userMapper.selectPage(page,null);//null是给条件查询器参数(这里不使用)page.getRecords().forEach(System.out::println);}

结果:
在这里插入图片描述

3.7 删除操作

  1. 根据id删除用户
 @Testvoid testDeleteById(){int result=userMapper.deleteById(1);System.out.println(result);}

结果:
在这里插入图片描述
2. 逻辑删除

物理删除:从数据库中直接删除
逻辑删除:并没有从数据库中删除而是通过一个变量让其不能使用(达到了所谓删除的目的),用于防止数据的丢失,相当于回收站的作用

  1. 增加一个删除标记字段在数据库中

在这里插入图片描述

  1. pojo增加属性并使用注解
@TableLogicprivate int flage;
  1. 配置逻辑删除组件
@Beanpublic ISqlInjector sqlInjector(){return  new LogicSqlInjector();}
  1. 配置文件中配置逻辑删除
mybatis-plus:global-config:db-config:logic-delete-value: 1logic-not-delete-value: 0
  1. 测试逻辑删除
  @Testvoid logicdelet(){userMapper.deleteById(2); //逻辑删除2号用户}

结果:数据并没有删除(但flage变成了1即数据已经被逻辑删除了)
在这里插入图片描述
然后测试一下是否能查询到逻辑删除的数据:

 @Testvoid testquery(){System.out.println(userMapper.selectById(2));}

结果:查询不到
在这里插入图片描述

3.8 性能分析插件(新版本的Mybatis-plus已将此插件移除)

慢sql:慢SQL指的是MySQL慢查询,是运行时间超过long_query_time值的SQL。真实的慢SQL通常会伴随着大量的行扫描、临时文件排序或者频繁的磁盘flush,直接影响就是磁盘IO升高,让正常的SQL变成了慢SQL,大面积执行超时。

在实际操作中我们会经常遇到一些慢sql,如何找出这些慢sql我们的Mybatis-plus也提供了 相应的插件:
性能分析插件:
性能分析拦截器,用于输出每条SQL语句及其执行时间。SQL性能执行分析,开发环境使用,超过指定时间停止运行,有助于发现问题。

  1. 编写性能分析插件
    //SQL执行效率插件@Bean@Profile({"dev","test"}) //设置 dev test 环境开启,保证我们的效率public PerformanceInterceptor performanceInterceptor(){PerformanceInterceptor  performanceInterceptor=new PerformanceInterceptor();performanceInterceptor.setMaxTime(1);  //设置sql的最大执行时间为1msperformanceInterceptor.setFormat(true);//是否开启格式化支持return performanceInterceptor;}
  • 在spring配置文件中配置环境为dev或者test环境
spring:profiles:active: dev
  1. 测试插件
  @Testvoid testPage(){Page page=new Page<>(2,5);userMapper.selectPage(page,null);page.getRecords().forEach(System.out::println);}

结果:sql运行时间为14ms超过了规定的时间所以执行失败
在这里插入图片描述

3.9 条件构造器

在前面使用的mybatis-plus提供的sql函数接口中,我们会发现我们把wrapper这个参数设置为了null,wrapper就是我们的条件构造器,用于写一些复杂的sql

  1. 使用wrapper进行复杂的查询操作:
 @Testvoid contextLoads(){//查询name不为空的用户,并且邮箱不为空的用户,年龄>21的用户QueryWrapper wrapper=new QueryWrapper();  //创建条件构造器wrapper.isNotNull("name");  //name不为空的查询条件wrapper.isNotNull("email");  //邮箱不为空wrapper.ge("age",12); //年龄大于12userMapper.selectList(wrapper).forEach(System.out::println);}

结果:
在这里插入图片描述

    @Testvoid contextLoads(){  //查询名字为menglei的用户//查询name不为空的用户,并且邮箱不为空的用户,年龄>21的用户QueryWrapper wrapper=new QueryWrapper();  //创建条件构造器wrapper.eq("name","menglei");userMapper.selectOne(wrapper);}

结果:
在这里插入图片描述
官网可以查看更多的使用方法

3.10 代码生成器

代码自动生成:AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

 public static void main(String[] args) {//构建一个代码自动生成器对象AutoGenerator autoGenerator=new AutoGenerator();//配置策略//1全局配置GlobalConfig gc=new GlobalConfig();String property = System.getProperty("user.dir"); //获取用户目录gc.setOutputDir(property+"/src/src/main/java");//代码文件的生成路径gc.setAuthor("chailong"); //设置作者gc.setFileOverride(false);//是否覆盖gc.setServiceName("%sService");//去service的i前缀gc.setIdType(IdType.ID_WORKER); //设置Id自增gc.setDateType(DateType.ONLY_DATE);//设置日期类型gc.setSwagger2(true);//设置swaggerautoGenerator.setGlobalConfig(gc);//2. 设置数据源DataSourceConfig dataSourceConfig = new DataSourceConfig();dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/mybatisplus");dataSourceConfig.setUsername("root");dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");dataSourceConfig.setPassword("123456");dataSourceConfig.setDbType(DbType.MYSQL);autoGenerator.setDataSource(dataSourceConfig);//3.设置包PackageConfig packageConfig = new PackageConfig();packageConfig.setModuleName("blog");packageConfig.setParent("com.chailong.getspring");packageConfig.setEntity("entity");packageConfig.setMapper("mapper");packageConfig.setService("service");packageConfig.setController("controller");autoGenerator.setPackageInfo(packageConfig);//4.策略配置StrategyConfig strategy = new StrategyConfig();strategy.setInclude("user"); //设置映射的表名strategy.setNaming(NamingStrategy.underline_to_camel);strategy.setColumnNaming(NamingStrategy.underline_to_camel);strategy.setEntityLombokModel(true);//自动生成lombokstrategy.setLogicDeleteFieldName("flage"); //设置逻辑删除名字//4.设置自动填充TableFill create_time = new TableFill("create_time", FieldFill.INSERT_UPDATE);TableFill update_time = new TableFill("update_time", FieldFill.INSERT_UPDATE);ArrayList arrayList = new ArrayList<>();arrayList.add(create_time);arrayList.add(update_time);strategy.setTableFillList(arrayList);//乐观锁strategy.setVersionFieldName("version");strategy.setRestControllerStyle(true);strategy.setControllerMappingHyphenStyle(true);autoGenerator.setStrategy(strategy);autoGenerator.execute();//执行}

运行结果:

  1. 生成的新的java目录(原来的内容没有被覆盖)
    在这里插入图片描述

相关内容

热门资讯

demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
阿西吧是什么意思 阿西吧相当于... 即使你没有受到过任何外语培训,你也懂四国语言。汉语:你好英语:Shit韩语:阿西吧(아,씨발! )日...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
阿西吧是什么意思 阿西吧相当于... 即使你没有受到过任何外语培训,你也懂四国语言。汉语:你好英语:Shit韩语:阿西吧(아,씨발! )日...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...