mybatis-plus 狂神说笔记

MyBatis-plus

CRUD

Insert

问题:mybatis-plus进行插入的时候会自动生成主键

    void insert() {
        User user = new User();
        user.setName("yogurt");
        user.setAge(15);
        user.setEmail("128@qq.com");
        userMapper.insert(user);
    }

image-20210315165845342

主键生成策略

/**
 * 数据库ID自增
 */
AUTO(0),
/**
 * 该类型为未设置主键类型
 */
NONE(1),
/**
 * 用户输入ID
 * 该类型可以通过自己注册自动填充插件进行填充
 */
INPUT(2),

/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
/**
 * 全局唯一ID (idWorker)
 */
ID_WORKER(3),
/**
 * 全局唯一ID (UUID)
 */
UUID(4),
/**
 * 字符串全局唯一ID (idWorker 的字符串表示)
 */
ID_WORKER_STR(5);

如果不配置默认的就是ID_WORKER,是使用雪花算法创建的全局唯一的ID。

update

public void Update(){
    User user = new User();
    user.setName("yogurt11");
    user.setAge(15);
    user.setEmail("128@qq.com");
    user.setId(1371386560893714434L);
    userMapper.updateById(user);
}

image-20210315171134021

mybatis-plus会自动拼接动态sql。

自动添加

创建时间、修改时间!这些个操作一遍都是自动化完成的,我们不希望手动更新!
阿里巴巴开发手册:所有的数据库表: gmt_create、 gmt_modified几乎所有的表都要配置上!而且需要自动化!

方式一:数据库级别实现,开发时不推荐使用,是不允许修改数据库的

  1. 改变表,默认值写上CURRENT_TIMESTAMP

    image-20210315172720807

  2. 测试成功image-20210315172804396

方式二:代码级别实现

  1. 修改表

    image-20210315172940427

  2. 修改实体类

    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    
  3. 添加处理器,mybatis-plus版本不同处理方式不一样,看官网

    @Slf4j
    @Component //一定要进行注册
    public class MyMetaObjectHandler implements MetaObjectHandler {
        @Override
        public void insertFill(MetaObject metaObject) {
            log.info("start insert fill ....");
            this.setFieldValByName("createTime",new Date(),metaObject);
            this.setFieldValByName("updateTime",new Date(),metaObject);
        }
    
        @Override
        public void updateFill(MetaObject metaObject) {
            log.info("start update fill ....");
            this.setFieldValByName("updateTime",new Date(),metaObject);
        }
    }
    
  4. 测试结果

    image-20210315173833997

乐观锁

简介

乐观锁:乐观锁总是认为线程是安全的,直到出现了问题再进行加锁处理。

  1. 取出一行记录时会取出里面的Version字段
  2. 更新字段是会带上这个Version字段,并判断该Version子段是否是之前取出的那个Veriosn
  3. 如果第二步没有问题则更新成功并且Version = Version + 1,如果判断失败则不会进行更新操作

实现步骤

  1. 在数据库里面添加veriosn字段

    image-20210315194158943

  2. 修改pojo

    @Version
    private Integer version;
    
  3. 在配置文件里面添加配置类

    @Configuration
    @MapperScan("com.yogurt.mybatisplus_study.mapper")
    public class MybatisPlusConfig {
    
        @Bean
        public MybatisPlusInterceptor optimisticLockerInnerInterceptor(){
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            return interceptor;
        }
    }
    
  4. 测试

    @Test
    public void optimisticLockTest() {
        //取出数据
        User user = userMapper.selectById(1L);
        user.setAge(50);
    
        //模拟多线程B对它操作
        User user1 = userMapper.selectById(1L);
        user1.setAge(55);
        userMapper.updateById(user1);
    
        //这次更新会失败,因为这样更新会覆盖掉user1的数据
        userMapper.updateById(user);
    }
    
  5. 结果

    image-20210315195457379

select

  1. 通过多个id查询

    public void selectByIds(){
        List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
        users.forEach(System.out::println);
    }
    
  2. 使用map进行条件查询

    @Test
    public void selectByMap(){
        HashMap<String, Object> map = new HashMap<>();
        map.put("name","yogurt");
        List<User> users = userMapper.selectByMap(map);
        users.forEach(System.out::println);
    }
    
  3. 分页查询

    1. 添加插件

      //分页插件
      @Bean
      public PaginationInterceptor paginationInterceptor () {
          return new PaginationInterceptor();
      }
      
    2. 查询

      @Test
      public void selectByPage(){
          Page<User> userPage = new Page<>(1,5);
          IPage<User> userIPage = userMapper.selectPage(userPage, null);
          //userPage和userIPage中都有数据
          userPage.getRecords().forEach(System.out::println);
          System.out.println("total -> " + userPage.getTotal() + "  pages -> " + userPage.getPages());
      }
      

delete

  1. 通过id删除,返回的是删除的行数
public void deleteById(){
    int result = userMapper.deleteById(1371394747445358594L);
    System.out.println("result -> " + result);
}

@Test
public void deleteByIds() {
    int result = userMapper.deleteBatchIds(Arrays.asList(1371392321954799617L, 1371392128916234242L));
    System.out.println("result -> " + result);
}
  1. 条件删除,返回的是删除的行数

    @Test
    public void deleteByMap() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("name","yogurt");
        int result = userMapper.deleteByMap(map);
        System.out.println("result -> " + result);
    }
    

逻辑删除

  1. 在数据库里面添加逻辑字段delete

    image-20210316143305105

  2. 实体类中添加属性

    @TableLogic
    private Integer deleted;
    
  3. 添加配置

    //逻辑删除插件
    @Bean
    public LogicSqlInjector logicSqlInjector() {
        return new LogicSqlInjector();
    }
    
    global-config:
      db-config:
        logic-delete-value: 1
        logic-not-delete-value: 0
    
  4. 测试

    可以看到删除操作变成了更新操作,就是把delete字段由0 -> 1

    image-20210316143518867

    执行查询的时候会自动拼接上 and delete = 0

    image-20210316143702362

总结

mybatis-plus插件的注入时,版本不同,注入的方式不一样。

mybatis-plus插件都在另外的依赖mybatis-plus-extension里

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-extension</artifactId>
    <version>3.0.5</version>
</dependency>

配置日志

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

条件构造器

  1. 名字和邮箱不为空且年龄 < 12的用户

    void test1() {
       //名字和邮箱不为空且年龄 < 12的用户
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.isNotNull("name")
                .isNotNull("email")
                .le("age",12);
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
    
  2. 查询名字为yogurt的用户,也可以通过map来实现

    void test2() {
        //查询名字为yogurt11的用户
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("name","yogurt11");
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
    
  3. 查询年龄 > 18 且 < 25的用户数量

    @Test
    void test3() {
        //查询年龄 >= 21 且 < 24的用户数量
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("age",21,24);
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
    
  4. 名字中不包含e的且以T开头邮箱的用户

    void test4() {
        //名字中不包含e的且以T开头邮箱的用户
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //likeRight = xx% 百分号在右边
        wrapper.notLike("name","e")
                .likeRight("email","t");
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
    

代码生成器

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

  1. 添加依赖

    <!--代码生成器-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>3.0.5</version>
    </dependency>
    <!--代码生成器模板引擎-->
    <dependency>
        <groupId>org.apache.velocity</groupId>
        <artifactId>velocity-engine-core</artifactId>
        <version>2.3</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.7.0</version>
    </dependency>
    
    
    <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.7.0</version>
    </dependency>
    
  2. 编写配置类

    public class CodeGeneration {
        public static void main(String[] args) {
            AutoGenerator mpg = new AutoGenerator();
            // 配置策略
            // 1、全局配置
            GlobalConfig gc = new GlobalConfig();
            String projectPath = System.getProperty("user.dir");
            gc.setOutputDir(projectPath+"/src/main/java");
            gc.setAuthor("iandf");
            gc.setOpen(false);
            gc.setFileOverride(false); // 是否覆盖
            gc.setServiceName("%sService"); // 去Service的I前缀
            gc.setIdType(IdType.ID_WORKER);
            gc.setDateType(DateType.ONLY_DATE);
            gc.setSwagger2(true);
            mpg.setGlobalConfig(gc);
    
            //2、设置数据源
            DataSourceConfig dsc = new DataSourceConfig();
            dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus_study?useUnicode=true&characterEncoding=utf8&useSSL=true");
            dsc.setDriverName("com.mysql.cj.jdbc.Driver");
            dsc.setUsername("root");
            dsc.setPassword("123456");
            dsc.setDbType(DbType.MYSQL);//设置数据库类型
            mpg.setDataSource(dsc);
    
            //3、包的配置
            PackageConfig pc = new PackageConfig();
            pc.setModuleName("user");
            pc.setParent("com.yogurt.mybatisplus_study");
            pc.setEntity("entity");
            pc.setMapper("mapper");
            pc.setService("service");
            pc.setController("controller");
            mpg.setPackageInfo(pc);
    
            //4、策略配置
            StrategyConfig strategy = new StrategyConfig();
            strategy.setInclude("user"); // 设置要映射的表名
            strategy.setNaming(NamingStrategy.underline_to_camel);//下划线转驼峰
            strategy.setColumnNaming(NamingStrategy.underline_to_camel);
            strategy.setEntityLombokModel(true); // 自动lombok;
            strategy.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);
            strategy.setTableFillList(tableFills);
            // 乐观锁
            strategy.setVersionFieldName("version");
            strategy.setRestControllerStyle(true);
            strategy.setControllerMappingHyphenStyle(true); //localhost:8080/hello_id_2
            mpg.setStrategy(strategy);
            mpg.execute(); //执行
        }
    }
    
  3. 执行之后生成的效果

    image-20210316161117404

原文地址:https://www.cnblogs.com/iandf/p/14544174.html