浅谈:MyBatis-Plus的CRUD与乐观锁,分页插件,逻辑删除

29 篇文章 0 订阅
12 篇文章 0 订阅

浅谈:MyBatis-Plus的CRUD与乐观锁,分页插件,逻辑删除

MyBatis-Plus官方文档连接

什么是MyBatis-Plus

请点击上面官方文档查看

代码演示:代码注释为功能详细解释

数据库

在这里插入图片描述

创建maven项目,基于springboot,mvc请参考官网

在这里插入图片描述

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.fs</groupId>
    <artifactId>MyBatisPlus-HelloWorld</artifactId>
    <version>1.0-SNAPSHOT</version>


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>


    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <!--     MyBatisPlus   -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>

        <!--     由于引入了MyBatisPlus ,就不需要引入这个了,因为MyBatis-puls底层就是对MyBatis封装   spring MyBatis-->
<!--        <dependency>-->
<!--            <groupId>org.mybatis.spring.boot</groupId>-->
<!--            <artifactId>mybatis-spring-boot-starter</artifactId>-->
<!--            <version>2.1.3</version>-->
<!--        </dependency>-->

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>


        <!--        druid-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.20</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
application.yml


spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://192.168.93.132:3306/test
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource #自定义数据源

# 配置开发环境
  profiles:
    active: dev
# 配置日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#配置逻辑删除
  global-config:
    db-config:
      logic-delete-field: flag  # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
主启动 MybatispulsHelloWorld
package com.fs;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MybatispulsHelloWorld {
    public static void main(String[] args) {
        SpringApplication.run(MybatispulsHelloWorld.class,args);
    }
}

MyBatis-Plus配置类
package com.fs.config;


import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration//配置类
//开启事务管理
@EnableTransactionManagement
//使用MyBatis-puls要使用@MapperScan扫描dao的包
@MapperScan("com.fs.dao")
public class MybatisPlusConfig {

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

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

    //逻辑删除 新版在yml配置了,这里不用配置
//    @Bean
//    public ISqlInjector sqlInjector(){
//        return new DefaultSqlInjector();
//    }



//    /**
//     * SQL执行效率插件 在3.2上已被移除
//     *
//     * @return
//     */
//    @Bean
//    @Profile({"dev"}) // 指定环境为dev生效
//    public PerformanceInterceptor performanceInterceptor() {
//        PerformanceInterceptor interceptor = new PerformanceInterceptor();
//        // sql美化打印
//        interceptor.setFormat(true);
//        // 设置SQL超时时间
//        interceptor.setMaxTime(5000L);
//        return interceptor;
//    }

}

自动填充功能类 MyMetaObjectHandler
package com.fs.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    //插入的时候充填策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        this.setFieldValByName("creatTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    //在跟新的时候充填策略
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}
pojo实体类User 属性对应数据库表的字段
package com.fs.pojo;

import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.apache.ibatis.annotations.Delete;

import java.util.Date;

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {
    //对应数据库中的主键,通过雪花算法
    @TableId(type = IdType.ID_WORKER)
    private Long id;

    private String name;
    private Integer age;
    private String email;

//    //在insert的时候插入
//    @TableField(fill = FieldFill.INSERT)
//    private Date creatTime;
//    @TableField(fill = FieldFill.INSERT_UPDATE)
//    private Date updateTime;

//    //版本
//    @Version//代表这是一个乐观锁的注解
//    @TableField(value = "`version`")//处理数据库关键字
//    private Integer version;

//    //逻辑删除
//    @TableLogic//这个注解就代表这个表中的字段存在逻辑
//    @TableField(value = "`delete`")//处理数据库关键字
//    private Integer delete;
}
mapper或者Dao接口 UserDao

这个接口要继承 BaseMapper<T>接口

package com.fs.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.fs.pojo.User;

//使用MyBatis-puls,只需要在UserDao接口上实现BaseMapper<实体类>
//这样,所有的CRUD都已经写完了,不需要在配置一大堆文件
public interface UserDao extends BaseMapper<User> {
}

测试类
package com.fs;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fs.dao.UserDao;
import com.fs.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

@SpringBootTest
public class MybatispulsHelloWorldTest {

    //userDao继承了BaseMapper.所有的方法都来自父类
    //我们也可以自己编写自己的扩展方法
    @Autowired
    private UserDao userDao;

    //测试查询所有
    @Test
    public void testUser(){
        //selectList的参数是一个Wrapper 条件构造器,不传就填null
        //查询全部用户
        List<User> users = userDao.selectList(null);
        for (User user : users) {
            System.out.println(user);
        }
    }

    //测试添加
    @Test
    public void testUserInsert(){
        //会自动根据你传递的对象的属性值不为null的来动态sql 就是xml 中的if
        /*
            private Long id;
    private String name;
    private Integer age;
    private String email;
         */
        //添加一个用户
//        userDao.insert(new User(null,"小付",18,"934226217@qq.com"));

        User user = new User();
        user.setName("测试2");
//        user.setAge(12);
        userDao.insert(user);
    }

    //测试更新
    @Test
    public void testUserupdateById(){
        /*
            private Long id;
    private String name;
    private Integer age;
    private String email;
         */
        User user = new User();
        user.setName("小强");
        user.setId(1293148203881086977L);
        //添加一个用户
        userDao.updateById(user);
    }


    //测试乐观锁成功
    @Test
    public void optimisticLocker(){
        User user = userDao.selectById(1L);
        user.setName("大大");
        user.setAge(1);
        user.setEmail("1213@qq.com");
        userDao.updateById(user);
    }


    //测试乐观失败,多线程下
    @Test
    public void optimisticLocker02(){
        //线程一
        User user = userDao.selectById(1L);
        user.setName("大大111");
        user.setAge(1);
        user.setEmail("1213@qq.com");

        //模拟另一个线程执行插队抄作
        User user1 = userDao.selectById(1L);
        user1.setName("大大22");
        user1.setAge(1);
        user1.setEmail("1213@qq.com");
        //插队,如果没有没有乐观锁就会被下面的覆盖
        userDao.updateById(user1);


        //由于上面更新操作后version+1,这里还是version.所以对比version值不一致,就不会对表中数据进行更新,这就是乐观锁
        userDao.updateById(user);
    }


    //测试查询
    @Test
    public void selectUser(){
        //selectList的参数是一个Wrapper 条件构造器,不传就填null
        //查询全部用户
        List<User> users = userDao.selectList(null);
        for (User user : users) {
            System.out.println(user);
        }
    }

    //根据ids查询
    @Test
    public void selectUserByIds(){
        //selectList的参数是一个Wrapper 条件构造器,不传就填null
        //查询ids用户
        List<User> users = userDao.selectBatchIds(Arrays.asList(1, 2, 3));
        for (User user : users) {
            System.out.println(user);
        }
    }

    //条件查询使用map操作
    @Test
    public void selectUserByMap(){

        HashMap<String, Object> map = new HashMap<>();
        map.put("name","小强");
        userDao.selectByMap(map).forEach(System.out::println);
    }

    //分页查询
    //配置拦截器
    @Test
    public void findPage(){
        //分页查询需要这个类,我们就new出来,传递当前页与每页条数
        Page<User> userPage = new Page<>(2,5);

        //Wrapper 没有就给null
        Page<User> users = userDao.selectPage(userPage, null);
        List<User> records = users.getRecords();
        records.forEach(System.out::println);
        long total = users.getTotal();
        System.out.println("总数:"+total);
    }

    //删除
    @Test
    public void deleteUser(){

        int i = userDao.deleteById(1);
        System.out.println(i);
//        userDao.deleteBatchIds(Arrays.asList(2,3,4));//批量id删除
//        userDao.deleteByMap(new HashMap<>());//根据条件删除
    }


    //逻辑删除
    @Test
    public void deleteUser02(){
        /*
        物理删除:从数据库中直接删除,持久化
        逻辑删除:在数据库中没有被移除,而是通过一个变量来让他失效!delete = 1

        //使用场景:管理员查询被删除的记录!,防止数据的丢失,类似于回收站

        //在数据表中增加delete字段
         */

        //配置逻辑删除后,执行的sql语句是更新操作,将delete的字段值为1,就实现了逻辑删除,查询的时候会自动拼接delete = 0
        //查询语句自动添加delete SELECT id,name,age,email,creat_time,update_time,`version`,`delete` FROM user WHERE `delete`=0
        userDao.deleteById(2);

    }
}
以查询所有为列子

说明我们不需要写任何sql.crud的sql,MyBatis-puls都帮我们自动生成,而且执行.
在这里插入图片描述

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值