-->

MybatisPlus

MybatisPlus

官方文档很详细!
MybatisPlus官方文档:https://baomidou.com

主键生成策略

分布式系统唯一ID生成:https://zhuanlan.zhihu.com/p/107939861

雪花算法

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。具体实现的代码可以参看https://github.com/twitter/snowflake。

主键自增

  1. 实体类字段上添加注解 @TableId(type = IdType.AUTO)
  2. 数据库对应字段必须设置自增

自动填充

  1. 注解填充字段 @TableField(.. fill = FieldFill.INSERT)

    // 字段添加填充
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    
    @TableField(fill = FieldFill.UPDATE)
    private Date updateTime;
    
  2. 自定义实现类 MyMetaObjectHandler 进行策略修改

    package com.test.handler;
    
    import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.ibatis.reflection.MetaObject;
    import org.springframework.stereotype.Component;
    
    import java.util.Date;
    
    @Slf4j
    @Component
    public class MyMetaObjectHandler 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);
        }
    }
    
    

乐观锁插件

当要更新一条记录的时候,希望这条记录没有被别人更新

乐观锁实现方式:

  • 取出记录时,获取当前 version
  • 更新时,带上这个 version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果 version 不对,就更新失败
  1. 数据表增加version字段

  2. 对应实体类添加字段

    @Version  // 乐观锁注解
    private Integer version;
    
  3. 注册组件

    package com.test.config;
    
    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @EnableTransactionManagement  // 自动管理事务
    @MapperScan("com.test.mapper")
    @Configuration
    public class MybatisPlusConfig {
        // 注册乐观锁插件
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
            mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            return mybatisPlusInterceptor;
        }
    }
    
  4. 测试

    @Test
    void testVersion(){
       // 线程1
       User user = userMapper.selectById(1L);
       user.setName("niu");
       user.setEmail("3123131");
    
       // 线程2 插队
       User user2 = userMapper.selectById(1L);
       user2.setName("yah");
       user2.setEmail("yes");
       userMapper.updateById(user2);
    
       // 自旋锁多次尝试提交
       userMapper.updateById(user);  // 如果没有乐观锁,线程1就会执行成功覆盖线程2的值
    }
    

分页插件

  1. 配置拦截器组件

    // 分页插件
    @Bean
    public MybatisPlusInterceptor Interceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
        return interceptor;
    }
    
  2. 测试

    	// 查询
    	@Test
    	void selectUser(){
    		User user = userMapper.selectById(1L);
    		System.out.println(user);
    		List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
    		users.forEach(System.out::println);
    
    		// 条件查询 Map
    		HashMap<String, Object> map = new HashMap<>();
    
    		// 自定义 查询条件
    		map.put("name","JOJO");
    
    		List<User> list = userMapper.selectByMap(map);
    		list.forEach(System.out::println);
    	}
    
    	// 分页查询
    	@Test
    	void selectPage(){
    		/**
    		 * 参数1:当前页  参数2:页面大小
    		 */
    		Page<User> page = new Page<>(1,5);
    		userMapper.selectPage(page,null);
    
    		System.out.println(page.getTotal());
    		page.getRecords().forEach(System.out::println);
    	}
    

逻辑删除

  1. 数据表中增加deleted删除标记字段

  2. 对应实体类添加字段

    @TableLogic  // 删除标记注解
    private Integer deleted;
    
  3. 配置文件

    mybatis-plus:
      global-config:
        db-config:
          logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
          logic-delete-value: 1 # 逻辑已删除值(默认为 1)
          logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
    

逻辑删除实际上就是修改表中删除标记的字段值

条件构造器

@Test
void contextLoads() {
   // 查询 name email 不为空 , age > 5
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper
            .isNotNull("name")
            .isNotNull("email")
            .ge("age",4);
    userMapper.selectList(queryWrapper).forEach(System.out::println);
}
@Test
void Test() {
    // 查询 name 为 Tom
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("name","Tom");
    System.out.println(userMapper.selectOne(queryWrapper));
}
@Test
void Test1() {
    // 查询 10 < age < 25 的人数
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.between("age",10,25);
    userMapper.selectList(queryWrapper).forEach(System.out::println);
    System.out.println(userMapper.selectCount(queryWrapper));
}
@Test
void Test2() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper
            // 通配符在左右   %e%
            .notLike("name","e")
            // 通配符在右    t%
            .likeRight("email","t");

    List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
    maps.forEach(System.out::println);
}
@Test
void Test3() {
    // 查询 name 不包含 e , email 以 e 开头
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    // id 子查询
    // 相当于
    // SELECT id,name,age,email,create_time,update_time,version,deleted FROM user WHERE deleted=0 AND (id IN (select id from user where id < 3))
    queryWrapper.inSql("id","select id from user where id < 3");

    List<Object> objects = userMapper.selectObjs(queryWrapper);
    objects.forEach(System.out::println);
}
@Test
void Test4() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    // 通过 id 进行降序排序
    queryWrapper.orderByDesc("id");
    userMapper.selectList(queryWrapper).forEach(System.out::println);
}

代码生成器

  1. 引入依赖

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>3.5.2</version>
    </dependency>
    
  2. 快速生成

    FastAutoGenerator.create("url", "username", "password")
        .globalConfig(builder -> {
            builder.author("baomidou") // 设置作者
                .enableSwagger() // 开启 swagger 模式
                .fileOverride() // 覆盖已生成文件
                .outputDir("D://"); // 指定输出目录
        })
        .packageConfig(builder -> {
            builder.parent("com.baomidou.mybatisplus.samples.generator") // 设置父包名
                .moduleName("system") // 设置父包模块名
                .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://")); // 设置mapperXml生成路径
        })
        .strategyConfig(builder -> {
            builder.addInclude("t_simple") // 设置需要生成的表名
                .addTablePrefix("t_", "c_"); // 设置过滤表前缀
        })
        .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
        .execute();
    
posted @   满城悬新筝  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示