Mybatis-plus学习02

今天完成了MyBatis-Plus(以下简称MP)的学习,深入了解了MP的特性和使用方式

1、主键生成策略

自动增长 AUTO INCREMENT
缺陷:分表操作需要考虑到上张表的最后一个id值是多少

UUID 每次生成随机唯一的值
缺陷:排序不方便

Redis原子操作

MP自带策略 snowflake算法
使用41bitz作为毫秒数,10bit作为机器的id(5个bit是数据中心,5个bit的机器id),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生4096个id),最后还有一个符号位,永远是0

MP可以自定义id生成规则,在主键字段上面添加@TableId
注解即可,方式如下:


自定义id生成规则

AUTO:自动增长
ID_WORKER:MP自带的策略,生成19位数值,数字类型使用这种策略,比如long
ID_WORKER_STR:MP自带的策略,生成19位数值,字符串类型使用这种策略
INPUT:设置id值,需要自己输入
NONE:没有策略,也是需要自己输入
UUID:随机策略

注:不写注解的话会自动识别字段类型,分配合适的自带策略

2、自动填充

1、表添加字段
create_time
update_time

2、添加实体类属性

传统添加时间的方式:

@Test
public void addUser() {
    User user = new User();
    user.setName("Lucy");
    user.setAge(21);
    user.setEmail("[email protected]");

    user.setCreateTime(new Date());
    user.setUpdateTime(new Date());

    int result = userMapper.insert(user);
    System.out.println("成功入库条数:" + result);
}

具体实现过程
(1)在实体类里面进行自动填充属性添加注解

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

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

(2)创建类,实现接口MetaObjectHandler里面的方法

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    /**
     * 使用mp实现添加操作,这个方法执行
    */
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime",new Date(), metaObject);
        this.setFieldValByName("updateTime",new Date(), metaObject);
    }

    /**
     * 使用mp实现修改操作,这个方法执行
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime",new Date(), metaObject);
    }
}

此时即可不设置updateTime和createTime的值完成数据自动填充

@Test
public void addUser() {
    User user = new User();
    user.setName("Lucy");
    user.setAge(21);
    user.setEmail("[email protected]");

    int result = userMapper.insert(user);
    System.out.println("成功入库条数:" + result);
}

3、乐观锁

主要解决 丢失更新问题
如果不考虑事务隔离性,产生读的问题:
脏读
不可重复读
幻读

如果不考虑事务隔离性,产生写的问题:
丢失更新问题:多个人同时操作同一条记录,最后提交的把之前提交的覆盖

解决方案:
1.悲观锁:串行,只能一个人进行操作,操作完后面的人才能进行操作,缺点是效率低下
2.乐观锁:提交事务的同时通过比较版本号,来实现数据操作,第一个人拿着1的版本号进行更新操作,操作完版本号变为2,第二个人此时也拿着1的版本号进行操作,提交事务的时候版本号对不上,操作失败;

实现MP乐观锁:
1、添加version字段
2、User实体类添加version属性

@Version
@TableField(fill = FieldFill.INSERT_UPDATE)
private Integer version;

3、配置乐观锁插件

@Configuration
@MapperScan("com.project.mpdemo.mapper")
public class MpConfig {

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

配置完执行新增和更新操作就会自动生成和更新版本号

/**
 * 测试乐观锁
*/
@Test
public void OptimisticLocker() {
    User user = userMapper.selectById(1283695307099598850L);
    user.setAge(22);
    int result = userMapper.updateById(user);
    System.out.println("成功更新条数:" + result);
}

4、MP分页操作

1、添加分页插件配置

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

2、编写分页代码

/**
 * 测试分页查询
*/
@Test
public void pageSelect() {
    Page page = new Page(1,4);
    userMapper.selectPage(page, null);
    List userList = page.getRecords();
    for(User user : userList) {
        System.out.println(user);
    }
    System.out.println(page.getCurrent());  //当前页
    System.out.println(page.getSize()); //每页显示记录数
    System.out.println(page.getTotal());    //总记录数
    System.out.println(page.getPages());    //总页数
    
    System.out.println(page.hasNext());
    System.out.println(page.hasPrevious());
}

5、MP逻辑删除实现

逻辑删除用于删除操作后,页面查询不到,但数据依然存在于数据库里,通过删除标记位实现
1、数据库添加标记位字段
2、实体类添加标记位属性,并添加逻辑删除注解

@TableLogic
private Integer deleted;

3、配置逻辑删除插件(如果默认配置跟MP一样的话则不需要)

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

4、添加删除标记位枚举值配置

@Bean
public ISqlInjector sqlInjector() {
    return new LogicSqlInjector();
}

5、测试

@Test
public void delUser() {
    int result = userMapper.deleteById(1283681589426958338L);
    System.out.println("成功删除数据条数:" + result);
}

6、MP性能分析插件

性能分析拦截器,用于输出每条SQL语句及其执行时间
SQL性能执行分析,开发环境使用,超过执行时间,停止运行。有助于发现问题

1、配置性能分析插件

/**
 * 性能分析插件
 *
 * 三种环境
 * dev 开发环境
 * test 测试环境
 * prod 生产环境
*/
@Bean
@Profile({"dev","test"})
public PerformanceInterceptor performanceInterceptor() {
    PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
    performanceInterceptor.setMaxTime(100);//ms,超过此处设置的SQL不执行
    performanceInterceptor.setFormat(true);
    return performanceInterceptor;
}

2、SpringBoot中设置dev环境

spring.profiles.active=dev

3、执行测试
4、打印结果


性能分析结果

7、MP实现复杂条件查询

MP条件构造器

推荐使用QueryWrapper构建查询条件
为什么:QueryWarpper比其父类Wrapper功能更强大(继承关系,字类可以使用父类的方法,父类不能使用子类的)

使用步骤
1、创建QueryWrapper对象
2、调用方法实现各种条件查询

@Test
public void selectQuery() {
    QueryWrapper queryWrapper = new QueryWrapper<>();

    //通过QueryWrapper设置条件
    // ge 大于、gt 大于等于、le 小于、lt 小于等于
    queryWrapper.ge("age",20);
    List userList = userMapper.selectList(queryWrapper);
    //eq 等于、ne 不等于
    queryWrapper.eq("name","Kitor");
    userList = userMapper.selectList(queryWrapper);

    //between
    queryWrapper.between("age",10,20);
    userList = userMapper.selectList(queryWrapper);
    //like
    queryWrapper.like("name","Ki");
    userList = userMapper.selectList(queryWrapper);
    //orderByDesc
    queryWrapper.orderByDesc("age","id");
    userList = userMapper.selectList(queryWrapper);
    //last
    queryWrapper.ge("age",30).eq("name","Kitor")
            .between("age",10,30).like("name","Ki")
            .orderByDesc("age","id");
    userList = userMapper.selectList(queryWrapper);

    //只查询这些字段
    queryWrapper.select("age","name","email");
    userList = userMapper.selectList(queryWrapper);
}

总结

通过今天的学习,发现所有的特性依然局限于单表操作(本人一直期待复杂查询的实现),但MP对于单表的特性可以说是史无前例了,几乎涵盖了全部实现方式,不需要再写SQL去进行其他操作,令我比较惊奇的是MP实现复杂条件查询这块,把几乎所有的SQL语法都覆盖进去了,极大地提升了开发效率(这边强吹一波,因为我感觉在Java里写SQL非常非常非常影响代码整体的美观性和整洁性),对比我现在使用的Hibernate,能够有效减少Java穿插SQL的这类情况,各位视而用之,也许MP不能完全满足你的需求,但加上MP你绝对不亏啊

你可能感兴趣的:(Mybatis-plus学习02)