Mybatis-plus使用笔记

参考资料

官方文档

参考链接:https://blog.csdn.net/qq_42682745/article/details/120626012
参考视频:https://www.bilibili.com/video/BV17E411N7KN

步骤

1、创建数据库以及对应的表

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户唯一标识',
  `account_id` varchar(100) DEFAULT NULL COMMENT '用户编号',
  `name` varchar(50) DEFAULT NULL COMMENT '用户名',
  `token` varchar(36) DEFAULT NULL COMMENT '主动设置的密钥',
  `gmt_create` bigint(50) DEFAULT NULL COMMENT '创建时间',
  `gmt_modified` bigint(50) DEFAULT NULL COMMENT '修改时间',
  `avatar_url` varchar(255) DEFAULT NULL COMMENT '头像地址',
  `deleted` int(10) DEFAULT NULL COMMENT '逻辑删除',
  `version` int(10) DEFAULT NULL COMMENT '乐观锁',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;

在真实开发中,version(乐观锁)、deleted(逻辑删除)、gmt_create(创建时间)、gmt_modified(更新\修改时间)

2、导入依赖

        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <!--mybatis-plus代码生成器-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.1</version>
        </dependency>
        <!--freemarker模板-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
        </dependency>	
    	

3、配置文件

#mysql 5 驱动不同   com.mysql.jdbc.Driver   补充:高版本是兼容低版本的
spring.datasource.username=root
spring.datasource.password=8848
spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
                                                        #useSSL:是否使用安全连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver


#MySQL8 驱动不同  com.mysql.cj.jdbc.Driver 、需要增加时区的配置


4、运行代码生成器

/代码自动生成器
public class anyuanCode {
    public static void main(String[] args) {

        FastAutoGenerator.create("jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8", "root", "8848")
                .globalConfig(builder -> {
                    builder.author("anyuan") // 设置作者
                            .commentDate("yyyy-MM-dd")//设置时间
                            .enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件
                            .outputDir("F:\\idea\\commulity\\src\\main\\java"); // 指定输出目录

                })
                .packageConfig(builder -> {
                    builder.parent("com.anyuan") // 设置父包名
                            .entity("model")//设置实体类包名
                            .service("service")//设置service包名
                            .serviceImpl("service.serviceImpl")//设置service实体类包名
                            .controller("controller")//设置实体类包名
                            .mapper("mapper")//设置实体类包名
                            .xml("mapper")//设置mapper.xml包名
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "F:\\idea项目\\zhang_hen\\src\\main\\resources\\mapper\\")); // 设置mapperXml生成路径
                })
                .strategyConfig(builder -> {
                    builder.addInclude("user","question") // 设置需要生成的表名
                            .addTablePrefix("t_", "c_") // 设置过滤表前缀
                            .serviceBuilder()//service配置策略
                            .formatServiceFileName("%sService")//service类名  %s适配,更具表明替换
                            .formatServiceImplFileName("%sServiceImpl")
                            .entityBuilder()//实体类适配策略
                            .enableLombok()//开启Lombok
                            .logicDeleteColumnName("deleted")//说明逻辑删除字段
                            .enableTableFieldAnnotation()//属性加上说明注解
                            .controllerBuilder()//controller策略配置
                            .formatFileName("%sController")
                            .enableRestStyle()//开启RestController
                            .mapperBuilder()//mapper配置策略
                            .superClass(BaseMapper.class)//继承 BaseMapper
                            .formatMapperFileName("%sMapper")
                            .enableMapperAnnotation()//@mapper 开启
                            .formatXmlFileName("%sMapper");
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                .execute();
    }
}
  • 注意点,我们需要在启动类上去扫描我们的mapper接口
//扫描我们的mapper文件夹
@MapperScan("com/anyuan/mapper")

扩展

配置日志

我们所有的sql现在是不可见的,我们希望知道他是怎么执行的,所以我们必须要看日志

#配置日志
    #这里使用默认的控制台输出
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

主键生成策略

分布式系统唯一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。

主键自增

我们需要配置逐渐自增

1、实体类字段上加 @TableId(type = IdType.AUTO)

2、数据库字段一定要是自增的

3、再次测试插入即可

其余的源码解释

public enum IdType {
    AUTO(0),//数据库id自增
    NONE(1),//未设置主键
    INPUT(2),//手动输入
    ASSIGN_ID(3),//默认策略 使用一个 64 bit 的 long 型的数字作为全局唯一 id。
    ASSIGN_UUID(4);//自动生成不含中划线的 UUID 作为主键。主键类型为 String,对应 MySQL 的表字段为 VARCHAR(32)
}

自动填充

创建时间、修改时间!这些个操作一般都是自动化完成的,我们不希望手动更新!

1、实体类的字段属性上增加注解操作

    @TableField(fill = FieldFill.INSERT)
    private Date createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

2、编写处理器来处理注解

@Component //要是该功能能够使用,需要将其加入到IOC容器中
@Slf4j     //加上日志
public class MyDateObjectHandler implements MetaObjectHandler {
    //插入式的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ........");

        this.setFieldValByName("create_time",new Date(),metaObject);
        this.setFieldValByName("update_time",new Date(),metaObject);
    }
    //更新时的填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ........");
        this.setFieldValByName("update_time",new Date(),metaObject);

    }
}

乐观锁

乐观锁:顾名思义十分乐观,他总是认为不会出现问题,无论干什么都不去上锁!如果出了问题,再次更新值测试

悲观锁:顾名思义十分悲观,他总是认为总是出现问题,无论干什么都会上锁!再去操作!

涉及字段:version 或 new version

主要讲解乐观锁机制!https://baomidou.com/pages/0d93c0/

  • 去除记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果 version 不对,就更新失败
乐观锁:
1、先查询,获得版本号 version = 1

-- A线程
update user set name = "kuang", version = version + 1
			where id = 2 and version = 1
			
-- B线程抢先修改,使得vsersion = 2,会导致A线程修改失败
update user set name = "kuang", version = version + 1
			where id = 2 and version = 1

测试MP的乐观锁(MP是 Mybatis_plus的简称)

1、在数据库中添加 version 字段 设置默认值为1

2、在代码中添加 version 属性

    @Version  //乐观锁Version注解
    private Integer version;

3、注册主件

//扫描我们的mapper文件夹
@MapperScan("com/anyuan/mapper")

@Configuration //代表该类是配置类
@EnableTransactionManagement // 自动管理事务
public class MybatisPlusConfig  {

    //注册乐观锁插件
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

4、测试乐观锁

//    测试乐观锁成功案例
@Test
void contextLoad3() {
    //1、查询用户信息
    User user = userMapper.selectById(1L);
    //2、修改用户信息
    user.setName("kuangsheng说");
    user.setEmail("123456@qq.com");
    //3、执行更新操作
    userMapper.updateById(user);

}

//    测试乐观锁失败案例!多线程下
@Test
void contextLoad4() {

    //线程1
    User user = userMapper.selectById(1L);
    user.setName("kuangsheng说11111");
    user.setEmail("123456@qq.com");
    System.out.println(user);
    //模拟另外一个线程执行了插队操作
    User user2 = userMapper.selectById(1L);
    user2.setName("kuangsheng说2222");
    user2.setEmail("123456@qq.com");
    userMapper.updateById(user2);


    userMapper.updateById(user);//如果没有乐观锁,就会覆盖插队线程的值

}

分页查询

MP其实也内置了分页插件

1、配置拦截器组件即可

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

    //注册乐观锁插件
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

    //注册分页插件
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
    return interceptor;
}

2、直接使用page对象即可

//测试分页查询
@Test
public void test7(){
    //参数一 :当前页
    //参数二:页面大小
    Page<User> page = new Page<>(2, 5);

    userMapper.selectPage(page,null);

    page.getRecords().forEach(System.out::println); 

}

逻辑删除

物理删除:从数据库中直接移除

逻辑删除:在数据库中没有被移除,而是通过一个变量让他失效!deleted = 0 => deleted = 1

管理员可以查看被删除的数据!防止数据的丢失,类似于回收站

1、在数据表中增加一个deleted字段

2、pojo实体类中增加属性

    @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)

实际代码操作

#配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
mybatis-plus.global-config.db-config.logic-delete-field=deleted

条件构造器

参考官方文档

posted @ 2022-03-01 19:27  黯渊  阅读(49)  评论(0编辑  收藏  举报