MybatisPlus学习笔记

MybatisPlus

学习笔记



一、实体类中对应主键生成策略

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

二、自动填充

创建时间,修改时间都是自动化完成,我们不希望手动去更新。两种实现方式:

  1. 数据库级别:
    在表中新建create_time和update_time,其中创建时间和更新时间的默认值均设置为CURRENT_TIMESTAMP,更新时间设置为自动更新。
    在这里插入图片描述
    进行测试:
@Test
    @Test
    void contextLoads() {
        User user = new User();
        user.setUsername("crisp");
        user.setPassword("2345");
        userMapper.insert(user);

    }

我没有手动对时间进行任何操作,查看日志和数据库如图
在这里插入图片描述
在这里插入图片描述
可以看到更新时间设置自动更新,因此实现自动数据填充,同时创建时间设置和更新时间设置为相同的默认值,故也得到更新。

  1. 代码级别:
    首先清除数据库时间自动更新以及默认值;
    其次在实体类相应字段添加自动填充注解;
@TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

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

最后自定义一个元数据处理器实现MetaObjectHandler中的插入字段以及更新字段处理方法,在代码如下:

@Slf4j
@Component//注入IOC容器中
public class MyMeteObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("going to insert fill");
        this.setFieldValByName("createTime", LocalDateTime.now(),metaObject);
        this.setFieldValByName("updateTime", LocalDateTime.now(),metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("going to update fill");
        this.setFieldValByName("updateTime", LocalDateTime.now(),metaObject);
    }
}

进行测试,实现自动填充:

 @Test
    void contextLoads() {
        User user = new User();
        user.setUsername("xcs");
        user.setPassword("2345");
        userMapper.insert(user);

    }

在这里插入图片描述

三、乐观锁

乐观锁:顾名思义,它总是认为不会出现问题,无论做什么都不去上锁,出现问题时,再次更新值测试
悲观锁:顾名思义十分悲观,它认为总是会出现问题,无论做什么都去上锁,再去操作。

乐观锁实现方式:

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

测试:

  1. user表新增version字段,默认值为1
    在这里插入图片描述
  2. 实体类添加对应的字段
    @Version
    private Integer version;
  1. 注册组件
@MapperScan("com.zpl.demo.mapper")//扫描mapper
@EnableTransactionManagement//事物管理
@Configuration//配置类
public class MybatisPlusConfig {

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

  1. 测试乐观锁
    单线程下:
@Test
    public void testOptimisticLocker()
    {
        User user = userMapper.selectById(2);

        user.setUsername("小小酥");
        user.setPassword("saswqeqw");

        userMapper.updateById(user);
    }

ID为2的数据更新,同时版本号得到更新
在这里插入图片描述
多线程下:

@Test
    public void testOptimisticLockerFail()
    {
        User user = userMapper.selectById(2);
        user.setUsername("嘿嘿");
        user.setPassword("saswqeqw");

        //插队线程
        User user2 = userMapper.selectById(2);
        user2.setUsername("星星");
        user2.setPassword("saswqeqw");
        userMapper.updateById(user2);

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

插队线程得以更新数据,版本号自动更新
在这里插入图片描述

四、查询操作

//测试批量查询
    @Test
    public void testQuery()
    {
       List<User> list =  userMapper.selectBatchIds(Arrays.asList(1,2,3));
       list.forEach(System.out::println);
    }

    //条件查询之一 使用map
    @Test
    public void testMapQuery()
    {
        Map map = new HashMap();
        map.put("username","hhh");
        map.put("password",2345);
        List<User> list =  userMapper.selectByMap(map);
        list.forEach(System.out::println);
    }


    //测试分页查询
    @Test
    public void testPagination()
    {
        //参数一:当前页
        //参数二:页面大小
        Page<User> page = new Page<>(1,5);
        userMapper.selectPage(page,null);
        page.getRecords().forEach(System.out::println);
    }

五、删除操作

//测试删除
    @Test
    public void testDeleteById()
    {
        userMapper.deleteById(3);
    }

    //批量删除
    @Test
    public void testDeleteBatchById()
    {
        userMapper.deleteBatchIds(Arrays.asList(2,4));
    }

    //测试map删除
    @Test
    public void testMapDelete()
    {
        Map map = new HashMap();
        map.put("username","hhh");
        userMapper.deleteByMap(map);
    }

六、逻辑删除

物理删除:将数据从数据库清除
逻辑删除:数据库中数据并未真正删除,使用标签字段控制。如cdeleted0->deleted1

  1. 数据库增加字段deleted。实体类添加deleted属性
 @TableLogic
    private Integer deleted;
  1. 配置
//逻辑删除组件
    @Bean
    public ISqlInjector sqlInjector(){
        return new LogicSqlInjector();
    }
#配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
  1. 测试
//测试删除
    @Test
    public void testDeleteById()
    {
        userMapper.deleteById(4);
    }

  1. 结果,逻辑删除实际执行的是更新操作
    在这里插入图片描述
    在这里插入图片描述

  2. 再次查询ID为4的数据

@Test
    public void query() {
        userMapper.selectById(4);
    }

6.结果,由于开启逻辑删除,SQL语句自动拼接deleted=0,即不能查询到数据
在这里插入图片描述

七、性能分析插件

开发时可能遇到一些慢SQL,MybatisPlus提供了性能分析插件帮助我们提高效率。
在MybatisPlus配置类中引入插件:

@Bean
    @Profile({"dev","test"})//设置dev、test环境开启,保证效率
    public PerformanceInterceptor performanceInterceptor(){
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(1);//设置SQL执行的最大时间,超过则不执行,单位毫秒
        performanceInterceptor.setFormat(true);//执行的SQL语句会格式化输出
        return performanceInterceptor;
    }

项目配置文件中设置开发环境:

#设置开发环境
spring.profiles.active=dev

再次执行一个简单的插入操作:

    @Test
    void contextLoads() {
        User user = new User();
        user.setUsername("wsd");
        user.setPassword("2345");
        userMapper.insert(user);

    }

控制台输出错误,由于我上面设置的SQL最大执行时间是1毫秒(根据实际情况进行设置),故大于该时间的操作均不能执行。可以看出性能分析插件已经生效,这有助于帮助我们找到慢SQL,进而优化。
在这里插入图片描述

八、条件构造器

复杂的SQL可以使用条件构造器实现,根据需要使用相应条件,使用链式编程的方式。**需要注意的是,各个条件之默认是and连接,需要or连接,直接使用or(),在其后添加条件。此外还包含了or嵌套、and嵌套、nested嵌套(正常嵌套 不带 AND 或者 OR)**一些常用操作如下:

@Test
    void test1()
    {
        //查询用户名不为空,邮件不为空,年龄大于等于30的用户
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper
                .isNotNull("username")
                .isNotNull("email")
                .ge("age",30);
        userMapper.selectList(wrapper).forEach(System.out::println);
    }

    @Test
    void test2()
    {
        //查询年龄在20与30岁之间的用户
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("age",20,30);
        Integer num = userMapper.selectCount(wrapper);
        System.out.println(num);
    }

    @Test
    void test3()
    {
        //模糊查询
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper
                .notLike("username","s")
                .likeRight("email","3");
        List<Map<String,Object>> maps = userMapper.selectMaps(wrapper);
        maps.forEach(System.out::println);
    }

    @Test
    void test4()
    {
        //多条件模糊查询(使用and嵌套,类似的还有or嵌套以及nested正常嵌套)
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper
                .notLike("username","s")
                .and(i -> i.like("age","1").or().like("password","5"));
        List<Map<String,Object>> maps = userMapper.selectMaps(wrapper);
        maps.forEach(System.out::println);
    }

    @Test
    void test5()
    {
        //in查询
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.inSql("id","select id from user where id >= 5");
        List<Object> objects = userMapper.selectObjs(wrapper);
        objects.forEach(System.out::println);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值