【MyBatis-Plus学习】关于MyBatis-Plus学习笔记

学完的感觉是:可以代替完成一些简单的CURD代码,复杂的SQL语句也可以用wrapper手动完成,但是感觉写成java代码对于后期维护可能比较费眼睛,不如xml写好完整的sql语句更清晰。不过自动填充、乐观锁、分页查询的功能挺方便,在自动注入的sql代码中也会自动加上去。自动生成基本代码插件也挺好,可以快速生成一个整体代码框架,就不用手动创建了(在非常多的数据库表的情况下就能体现出它的优点了),我们只需要往里面写逻辑代码即可。

Mybatis Plus

可以节省大量时间 所有CRUD代码都可以自动化完成

创建学习环境

1、创建数据库

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

3、加入数据

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');

4、创建一个普通的springboot项目,导入基本依赖

<dependencies>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

CRUD扩展

插入操作

主键生成策略

默认 ID_WORKER 全局唯一id

public enum IdType {
    
    
    /**
     * 数据库ID自增
     * <p>该类型请确保数据库设置了 ID自增 否则无效</p>
     */
    AUTO(0),
    /**
     * 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
     */
    NONE(1),
    /**
     * 用户输入ID
     * <p>该类型可以通过自己注册自动填充插件进行填充</p>
     */
    INPUT(2),

    /* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
    /**
     * 分配ID (主键类型为number或string),
     * 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(雪花算法)
     *
     * @since 3.3.0
     */
    ASSIGN_ID(3),
    /**
     * 分配UUID (主键类型为 string)
     * 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-",""))
     */
    ASSIGN_UUID(4);

    private final int key;

    IdType(int key) {
    
    
        this.key = key;
    }
}

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

更新操作

自动填充

创建时间、修改时间,这些操作是自动化完成的,

阿里巴巴开发手册:所有的数据库表:gmt_create、gmt_modified 几乎在所有的表都要配置上,而且需要自动化。

方式一:数据库修改

请添加图片描述

请添加图片描述

插入时,两个字段都等于当前时间,插入更新时,update_time更新当前时间

更新测试:

请添加图片描述

方式二

1、注解 @TableField

请添加图片描述

2、编写处理器

import java.time.LocalDateTime;

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    
    
    @Override
    public void insertFill(MetaObject metaObject) {
    
    
        log.info("start insert fill ....");
        this.strictInsertFill(metaObject,"createTime", LocalDateTime.class,LocalDateTime.now());
    }

    @Override
    public void updateFill(MetaObject metaObject) {
    
    
        log.info("start update fill ....");
        this.strictUpdateFill(metaObject,"createTime", LocalDateTime.class,LocalDateTime.now());
    }
}

注意事项:

  • 填充原理是直接给entity的属性设置值!!!
  • 注解则是指定该属性在对应情况下必有值,如果无值则入库会是null
  • MetaObjectHandler提供的默认方法的策略均为:如果属性有值则不覆盖,如果填充值为null则不填充
  • 字段必须声明TableField注解,属性fill选择对应策略,该声明告知Mybatis-Plus需要预留注入SQL字段
  • 填充处理器MyMetaObjectHandler在 Spring Boot 中需要声明@Component@Bean注入
  • 要想根据注解FieldFill.xxx字段名以及字段类型来区分必须使用父类的strictInsertFill或者strictUpdateFill方法
  • 不需要根据任何来区分可以使用父类的fillStrategy方法
  • update(T t,Wrapper updateWrapper)时t不能为空,否则自动填充失效

3、测试:

插入

请添加图片描述

更新

请添加图片描述

乐观锁

总是认为不会出现问题,无论做什么,都不去上锁,如果出现问题,再次更新值测试

用version检测更新

实现方式;

  • 取出记录时,获取当前的version
  • 更新时,带上这个version
  • 执行更新时,set version = new version where version = oldversion
  • 如果version 不对,就更新失败

1、数据库增加version字段

2、同步实体类

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

3、注册组件

@MapperScan("com.freeze.mybatisplus.mapper")
@EnableTransactionManagement //事务管理
@Configuration //配置类
public class MyBatisPlusConfig {
    
    

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

}

4、测试

成功更新

//测试乐观锁成功
@Test
void testOptimisticLocker(){
    
    
    //查询用户信息
    User user = userMapper.selectById(1L);
    //修改用户信息
    user.setName("xibala");
    user.setEmail("[email protected]");
    //更新
    userMapper.updateById(user);

}

请添加图片描述

失败更新

@Test
void testOptimisticLocker2(){
    
    
    User user1 = userMapper.selectById(1L);
    user1.setName("xibala111");
    user1.setEmail("[email protected]");

    //模拟另一个 线程插队执行更新操作
    User user2 = userMapper.selectById(1L);
    user2.setName("xibala222");
    user2.setEmail("[email protected]");
    userMapper.updateById(user2);

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

}

请添加图片描述

悲观锁:

总是认为会出现问题,无论做什么都会上锁,再去操作

查询操作

// 测试查询
@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);
}
// 按条件查询之一使用map操作
@Test
public void testSelectByBatchIds(){
    
    
HashMap<String, Object> map = new HashMap<>();
// 自定义要查询
map.put("name","狂神说Java");
map.put("age",3);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}

分页查询

1、使用原始limit进行分页

2、pageHelper第三方插件

3、MP其实内置了分页插件

如何使用:

1、添加组件

@MapperScan("com.freeze.mybatisplus.mapper")
@EnableTransactionManagement //事务管理
@Configuration //配置类
public class MyBatisPlusConfig {
    
    

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
    
    
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//分页插件
        return interceptor;
    }

}

2、直接使用Page对象即可!

请添加图片描述

删除操作

// 测试删除
@Test
public void testDeleteById(){
    
    
userMapper.deleteById(1240620674645544965L);
}
// 通过id批量删除
@Test
public void testDeleteBatchId(){
    
    
userMapper.deleteBatchIds(Arrays.asList(1240620674645544961L,124062067464554496
2L));
}
// 通过map删除
@Test
public void testDeleteMap(){
    
    
HashMap<String, Object> map = new HashMap<>();
map.put("name","狂神说Java");
userMapper.deleteByMap(map);
}

逻辑删除

在数据库中没有被移出,而是通过一个变量来让他失效

防止数据的丢失 回收站原理

说明:

只对自动注入的 sql 起效

测试

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

2、在实体类增加字段和注解(新版本不用加注解,只需要在配置文件中标注字段名)

3、添加配置(新版本不需要添加组件)

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted # 全局逻辑删除的实体字段名
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

4、测试

删除

请添加图片描述

查询

请添加图片描述

条件构造器

Wrapper,写一些比较复杂的sql语句时,就使用它

条件构造器 | MyBatis-Plus (baomidou.com)

自动生成代码插件

前提:设计好数据库

1、导入依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.2</version>
</dependency>

2、创建一个java文件编写快速生成代码

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();

具体配置参考:https://baomidou.com/pages/981406

学习视频来源:B站Java狂神说

猜你喜欢

转载自blog.csdn.net/adminguojieBin/article/details/123797314