爬梯:MyBatis-Plus全解析

学习资源整理自:B站《狂神说》

建议搭配官网一起学习,MyBatis Plus是国人开发的,官网教程还是很通俗易懂的:https://mybatis.plus

MyBatis-Plus

MyBatis-Plus全面学习与应用

1、Hello MyBatis-Plus

1. 官网提供的数据库环境

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

2. 创建SpringBoot项目,导入相应jar包

<dependency>
    <groupId>mysqlgroupId>
    <artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
dependency>
<dependency>
    <groupId>com.baomidougroupId>
    <artifactId>mybatis-plus-boot-starterartifactId>
    <version>3.0.5version>
dependency>

3. 编写Dao

/**
 * 继承 mybatis-plus 的Mapper
 * 基本的CRUD已经全部写完
 * @author: stone
 * @create: 2020-09-03 00:04
 */
@Repository  
public interface ISmartUserDao extends BaseMapper<SmartUser> {
     
}

4. 测试运行

@Autowired
ISmartUserDao smartUserDao;

@Test
void contextLoads() {
     
    List<SmartUser> smartUsers = smartUserDao.selectList(null);
    smartUsers.forEach(System.out::println);
}

console

爬梯:MyBatis-Plus全解析_第1张图片

配置日志

让sql可见

使用控制台输出

# 日志配置
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

console

爬梯:MyBatis-Plus全解析_第2张图片

至此入门结束。

2、主键生成策略

@Test
void testInsert(){
     
    SmartUser smartUser = new SmartUser();
    smartUser.setName("石似心");
    smartUser.setAge(3);
    smartUser.setEmail("[email protected]");
    // smartUser.setId();
    System.out.println(smartUserDao.insert(smartUser));
    System.out.println(smartUser);
}

console

爬梯:MyBatis-Plus全解析_第3张图片

自动添加了ID

ID主键生成策略

主键注解:@TableId

源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({
     ElementType.FIELD})
public @interface TableId {
     
    String value() default "";

    IdType type() default IdType.NONE;
}
public enum IdType {
     
    AUTO(0),	// 数据库ID自增
    NONE(1),	// 未设置主键
    INPUT(2),	// 手动输入
    ID_WORKER(3),	// 默认的全局唯一ID
    UUID(4),	// 全局唯一UUID
    ID_WORKER_STR(5);	// ID_WORKER 字符串表示法

    private int key;
    private IdType(int key) {
     
        this.key = key;
    }
    public int getKey() {
     
        return this.key;
    }
}

AUTO

@TableId(type = IdType.AUTO)

这个auto的意思是使用数据库表的自增规则,+1,所以需要配合地去把数据库表ID设置为自增列,否则会报错~

ID_WORKER 默认主键生成策略,全局唯一

@TableId(type = IdType.ID_WORKER)

雪花算法 64位

分布式系统唯一ID,Twitter的snowflake,开源的分布式ID生成算法,结果是一个long类型的ID:

1、使用41bit作为毫秒数;

2、10bit作为机器的ID(5个bit是数据中心:北京、香港、西雅图…,5个bit是机器的ID);

3、12bit作为毫秒内的流水号(每个节点在每毫秒内可以生成4086个ID);

4、最有一个符号永远是0。

参考代码:https://github.com/twitter/snowflake

3、自动填充处理

@Test
void testUpdate(){
     
    SmartUser smartUser = new SmartUser();
    smartUser.setId(8l);
    smartUser.setName("周杰伦");
    smartUser.setAge(10);
    System.out.println(smartUserDao.updateById(smartUser));
}

console

爬梯:MyBatis-Plus全解析_第4张图片

sql由mybatis plus动态拼接

alibaba开发手册:所有的数据库表都有 gmt_create、gmt_modified 这两个字段,而且需要自动化。

自动填充字段

1、数据库级别(企业都不会这么干)

爬梯:MyBatis-Plus全解析_第5张图片

2、代码级别

首先看到字段注解 @TableField

源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({
     ElementType.FIELD})
public @interface TableField {
     
    String value() default "";
    String el() default "";
    boolean exist() default true;
    String condition() default "";
    String update() default "";
    FieldStrategy strategy() default FieldStrategy.DEFAULT;
    FieldFill fill() default FieldFill.DEFAULT;
    boolean select() default true;
}

其中有个 FieldFill 字段填充对象,就是他了!

源码: 这里指的是,在进行什么类型的操作时,才执行fill
public enum FieldFill {
     
    DEFAULT,	// 默认,不处理
    INSERT,	
    UPDATE,
    INSERT_UPDATE;
    private FieldFill() {
     
    }
}

修改实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class SmartUser {
     

    @TableId(type = IdType.ID_WORKER)
    private Long id;
    private String name;
    private int age;
    private String email;

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

填充什么东西咧,这里mybatisplus还没智能到去判断类型,所以需要写一个处理类,告诉他填充什么内容。

handler

/**
 * 自动填充数据处理类
 * @author: stone
 * @create: 2020-09-04 00:45
 */
@Slf4j
@Component
public class MyMetaHandler implements MetaObjectHandler {
     

    @Override
    public void insertFill(MetaObject metaObject) {
     
        log.info("insertFill is action ...");
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
     
        log.info("updateFill is action ...");
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

执行插入:自动生成时间

爬梯:MyBatis-Plus全解析_第6张图片

执行更新:自动填充更新时间

爬梯:MyBatis-Plus全解析_第7张图片

4、数据乐观锁

给数据添加上乐观锁,既版本号控制;

主要适用场景

意图:

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

1、首先要在数据库表上加上version字段;

2、更新实体类

@Version 
private int version;

3、添加配置类,配置乐观锁

/**
 * @author: stone
 * @create: 2020-09-04 22:17
 */
@MapperScan("com.ssx.studymybatisplus.dao")
@EnableTransactionManagement
@Configuration
public class MyBatisPlusConfig {
     

    //注册乐观锁
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor(){
     
        return new OptimisticLockerInterceptor();
    }
}

4、代码测试~

/**
 * 测试乐观锁,模拟插队
 * @throws InterruptedException
 */
@Test
void testOptimisticLock() throws InterruptedException {
     
    // smartUser1
    SmartUser smartUser1 = smartUserDao.selectById(1l);
    smartUser1.setName("差不多先生");

    // smartUser2
    SmartUser smartUser2 = smartUserDao.selectById(1l);
    smartUser2.setName("不用去猜");
    // smartUser2 插队先操作了数据库

    System.out.println("smartUser2 updated => "+smartUserDao.updateById(smartUser2));
    TimeUnit.SECONDS.sleep(1);
    System.out.println("smartUser1 updated => "+smartUserDao.updateById(smartUser1));
}

console

爬梯:MyBatis-Plus全解析_第8张图片

如果仍希望update smartUser1,可以使用自旋锁,再次去获取版本号更新(递归锁)

5、分页查询

  • sql关键字limit

  • pageHelper分页插件

  • MyBatisPlus内置分页工具

1、从官网可以获取到配置分页拦截器的代码

@Bean
public PaginationInterceptor paginationInterceptor() {
     
    return new PaginationInterceptor();
}

里面可以配置很多信息:

// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
//paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));

2、使用分页的方法查询

@Test
void testPage(){
     
    // 当前页码 1 ,单页的记录数 3
    Page<SmartUser> page = new Page<>(1,3);

    IPage<SmartUser> smartUserIPage = smartUserDao.selectPage(page, null);
    List<SmartUser> records = smartUserIPage.getRecords();
    records.forEach(System.out::println);
}

console

爬梯:MyBatis-Plus全解析_第9张图片

查询方法中的 page 对象,会在查询之后得到回写:

爬梯:MyBatis-Plus全解析_第10张图片

可以获取当前页的相关信息

6、逻辑删除

当用户进行删除操作之后,将数据的状态改为“删除”,但并不会真正的把数据从数据库中删除,进而保护了数据,增强安全性。

学习三步走~

1、数据库加字段

deleted int(1) 默认0

行规~ 0:否;1:是;

2、更新实体类

@TableLogic
private int deleted;

3、添加配置~

application.properties

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

注册逻辑删除拦截器

@Bean
public LogicSqlInjector logicSqlInjector(){
     
    return new LogicSqlInjector();
}

4、代码测试

@Test
void testLogicDelete(){
     
    //执行删除
    smartUserDao.deleteById(2l);

    //查询删除的数据
    System.out.println(smartUserDao.selectById(2l));
}

console

爬梯:MyBatis-Plus全解析_第11张图片

可以看到,执行delete实则执行的是update sql,

然后执行select自动添加了deleted=0操作。

7、性能分析插件

可以查看sql的执行时间,可以格式化sql代码,可以设置sql执行超过多少时间则抛出异常…

但是官网说3.x后的版本移除次插件,建议使用第三方插件…

不过经测试,3.0.2版本还是可以用,代码还没删除也没画横线…

配置拦截器

/**
 * SQL执行效率插件
 */
@Bean
@Profile({
     "dev","test"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {
     
    PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
    performanceInterceptor.setFormat(true);
    performanceInterceptor.setMaxTime(1000);
    return performanceInterceptor;
}

代码测试

smartUserDao.selectList(null);

console

爬梯:MyBatis-Plus全解析_第12张图片

8、条件构造器

官方API:https://mybatis.plus/guide/wrapper.html#abstractwrapper

操作

QueryWrapper wrapper = new QueryWrapper<>();

wrapper.eq()

拼装查询条件进行查询

由于工作中常用,就不写测试代码了!

9、代码生成器

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

官方API:https://mybatis.plus/guide/generator.html#%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B

官网有默认的配置,直接拷下来改~

你可能感兴趣的:(java,mybatis)