本笔记根据B站 遇见狂神说的MyBatis-Plus视频整理
视频链接: https://www.bilibili.com/video/BV17E411N7KN 
快速入门 使用SpringBoot初始化快速构建
导入依赖 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18          <dependency >              <groupId > mysql</groupId >              <artifactId > mysql-connector-java</artifactId >          </dependency >          <dependency >              <groupId > org.projectlombok</groupId >              <artifactId > lombok</artifactId >          </dependency >          <dependency >              <groupId > com.baomidou</groupId >              <artifactId > mybatis-plus-boot-starter</artifactId >              <version > 3.0.5</version >          </dependency > 
说明:我们使用mybatis-plus可以节省我们大量的代码,尽量不要同时导入mybatis和mybatis-plus
连接数据库 
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 
传统方式:pojo-dao(连接mybatis,配置mapperxml文件)-service controller
使用了mybatis-plus之后 
pojo
@Data @NoArgsConstructor @AllArgsConstructor public  class  User   {          private  Long id;     private  String name;     private  Integer age;     private  String email; }
mapper接口
@Mapper @Repository public  interface  UserMapper  extends  BaseMapper <User >  {           }
注意点:需要在启动类上加入一个注解 @MapperScan("com.jinan.mapper"),用来扫描我们的mapper文件夹
使用,在测试类中测试
          @Autowired      private  UserMapper userMapper;     @Test      void  contextLoads ()   {                           List<User> users = userMapper.selectList(null );         users.forEach(System.out::println);     }
结果
User(id=1, name=张三, age=18, email=11@qq.com) User(id=2, name=李四, age=18, email=11@qq.com) User(id=3, name=王五, age=12, email=11@qq.com) User(id=4, name=孙六, age=13, email=11@qq.com)
思考问题?
1、SQL谁帮我们写的? MyBatis-Plus
2、方法哪里来的? MyBatis-Plus
配置日志 我们所有的SQL现在都是不可见的,我们希望知道它是怎么执行的,所以我们必须要有日志!
mybatis-plus.configuration.log-impl =org.apache.ibatis.logging.stdout.StdOutImpl 
配置完日志之后,后面的学习就需要注意这个自动生成的SQL。
CRUD扩展 插入操作 insert 插入
@Test public  void  testInsert ()  {     User user = new  User();     user.setName("测试" );     user.setAge(20 );     user.setEmail("22@qq.com" );     int  insert = userMapper.insert(user);     System.out.println(insert);      System.out.println(user);  }
数据库插入的id的默认值为:全局的唯一id
主键生成策略 默认 ID_WORKER 全局唯一ID
分布式系统唯一id生成:https://www.cnblogs.com/haoxinyue/p/5208136.html 
雪花算法:
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0
主键自增 AUTO
我们需要配置主键自增:
1、实体类字段上==@TableId(type = IdType.AUTO)==
2、数据库字段一定要是自增的!
3、重新测试即可
其余的源码解释
public  enum  IdType  { AUTO,  NONE,  INPUT,  ID_WORKER,  UUID,  ID_WORKER_STR;   }
更新操作     @Test     public  void  testUpdate ()  {        User user = new  User();                user.setId(5L );        user.setName("振续来也" );        user.setAge(99 );                int  i = userMapper.updateById(user);        System.out.println(i);    }
  所有的SQL自动给你动态配置
自动填充 创建时间、修改时间!这些操作一般都是自动化完成的,我们不希望手动更新!
阿里巴巴开发手册:所有的数据库表:gmt_create、gmt_modified几乎所有的表都要配置上,而且需要自动化
方式一:数据库级别(工作中不允许你修改数据库)
1、在表中新增字段 create_time、update_time
2、添加对应实体类
private  Date createTime;private  Date updateTime;
3、测试查看
方式二:代码级别
1、删除数据库的默认值,更新操作!
2、实体类的字段属性上需要增加注解
@TableField(fill = FieldFill.INSERT) private  Date createTime;@TableField(fill = FieldFill.INSERT_UPDATE) private  Date updateTime;
3、编写处理器来处理这个注解即可!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Slf4j @Component  public  class  MyDataHandler  implements  MetaObjectHandler   {          @Override      public  void  insertFill (MetaObject metaObject)   {         log.info("开始插入" );                  this .setFieldValByName("createTime" ,new  Date(),metaObject);         this .setFieldValByName("updateTime" ,new  Date(),metaObject);     }          @Override      public  void  updateFill (MetaObject metaObject)   {         log.info("开始更新" );         this .setFieldValByName("updateTime" ,new  Date(),metaObject);     } }
4、测试插入
5、测试更新 观察时间变化即可
乐观锁 在面试过程中,我们经常会被问到乐观锁,悲观锁!这个其实非常简单
乐观锁:顾名思义,十分乐观,它总是认为不会出现问题,无论干什么都不去上锁!如果出现了问题,再次更新值进行测试!
悲观锁:顾名思义,十分悲观,它总是认为出现问题,无论干什么都会上锁!再去操作!
version、new version
乐观锁机制 
当要更新一条记录的时候,希望这条记录没有被别人更新 乐观锁实现方式:
取出记录时,获取当前version 更新时,带上这个version 执行更新时, set version = newVersion where version = oldVersion 如果version不对,就更新失败 乐观锁:1 、先查询,获得版本号 version =  1      update user  set  name =  "jinna",version =  version +  1      where  id =  2  and  version = 1           update user  set  name =  "jinna",version =  version +  1      where  id =  2  and  version = 1 
测试mybatis-plus的乐观锁插件
1、给数据库增加version字段
2、实体类加对应的字段
@Version  private  Integer version;
3、注册组件
@MapperScan("com.jinan.mapper") @EnableTransactionManagement   @Configuration  public  class  MyBatisPlusConfig   {          @Bean      public  OptimisticLockerInterceptor optimisticLockerInterceptor ()  {         return  new  OptimisticLockerInterceptor();     } }
4、测试一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28      @Test      public  void  testOptimisticLocker ()  {                  User user = userMapper.selectById(1L );                  user.setName("乐观锁" );                  userMapper.updateById(user);     }          @Test      public  void  testOptimisticLocker2 ()  {                  User user = userMapper.selectById(1L );         user.setName("乐观锁" );                  User user1 = userMapper.selectById(1L );         user.setName("啦啦啦" );                  userMapper.updateById(user);          userMapper.updateById(user1);     }
多线程下 
  查询操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Test public  void  testSelectById ()  {     User user = userMapper.selectById(1L );     System.out.println(user); }@Test public  void  testSelectByBatchId ()  {     List<User> users = userMapper.selectBatchIds(Arrays.asList(1 , 2 , 3 ));     users.forEach(System.out::println); }@Test public  void  testSelectByBatchIds ()  {     HashMap<String, Object> map = new  HashMap<>();          map.put("name" ,"啦啦啦" );     List<User> users = userMapper.selectByMap(map);     users.forEach(System.out::println); }
分页查询 分页使用十分多
1、原始的limit进行分页
2、pageHelper 第三方插件
3、mybatis-plus内置了分页插件
如何使用
1、配置拦截器组件 ,官网有示例
@Bean public  PaginationInterceptor paginationInterceptor ()   {     return  new  PaginationInterceptor(); }
2、测试
     @Test      public  void  testPage ()  {                           Page<User> Page = new  Page<>(2 ,5 );         userMapper.selectPage(Page,null );                  Page.getRecords().forEach(System.out::println);         System.out.println(Page.getTotal());         }
删除操作 基本的删除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Test public  void  testDeleteById ()  {     userMapper.deleteById(1L ); }@Test public  void  testDeleteBatchIds ()  {     userMapper.deleteBatchIds(Arrays.asList(1 ,2 ,3 )); }@Test public  void  testDeleteMap ()  {     HashMap<String, Object> map = new  HashMap<>();     map.put("name" ,"啦啦啦" );     userMapper.deleteByMap(map); }
我们在工作中会遇到一些问题:逻辑删除!
逻辑删除 物理删除:从数据库中直接移除
逻辑删除:在数据库中没有被移除,而是通过一个变量来让他失效! deleted = 0 —-》 deleted = 1
管理员可以查看被删除的记录!防止数据的丢失,类似于回收站
测试 
1、在数据库表中增加一个 deleted 字段
2、补充实体类
@TableLogic private  Integer deleted;
3、配置
@Bean public  ISqlInjector sqlInjector ()  {     return  new  LogicSqlInjector(); }
application.properties
#配置逻辑删除 mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-not-delete-value=0
4、测试删除
执行的其实是更新操作,记录依旧在数据库中,但是值已经变化了
查询的时候回自动过滤被逻辑删除的数据
以上的所有CRUD操作及其扩展操作,必须精通,会大大的提高效率
性能分析插件 我们在平时的开发中,会遇到一些慢SQL。
mybatis-plus也提供了性能分析插件,如果超过这个时间就会停止运行!
新版本移除了性能分析插件,可以使用一个新的插件
官方文档:https://mybatis.plus/guide/p6spy.html 
条件构造器 十分重要:Wrapper
官方文档:https://mybatis.plus/guide/wrapper.html#abstractwrapper 
1、测试一:
@Test void  contextLoads ()   {          QueryWrapper<User> wrapper = new  QueryWrapper<>();     wrapper         .isNotNull("name" )         .isNotNull("email" );     userMapper.selectList(wrapper).forEach(System.out::println);  }
2、测试二:
@Test public  void  test2 ()   {          QueryWrapper<User> wrapper = new  QueryWrapper<>();     wrapper.eq("name" , "王五" );     User user = userMapper.selectOne(wrapper);       System.out.println(user); }
3、测试三:
@Test void  test3 ()   {          QueryWrapper<User> wrapper = new  QueryWrapper<>();     wrapper.between("age" , 12 , 26 );     Integer integer = userMapper.selectCount(wrapper);     System.out.println(integer); }
4、测试四:
@Test void  test4 ()  {     QueryWrapper<User> wrapper = new  QueryWrapper<>();          wrapper             .notLike("name" ,"呀" )             .likeRight("email" ,"2" );     List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);     maps.forEach(System.out::println); }
5、测试五:
@Test void  test5 ()  {     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); }
6、测试六
@Test void  test6 ()   {     QueryWrapper<User> wrapper = new  QueryWrapper<>();          wrapper.orderByDesc("id" );     List<User> users = userMapper.selectList(wrapper);     users.forEach(System.out::println); }