大数据最全学习SSM中的M+(MyBatis Plus 3(5),源码+原理+手写框架

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

}


* 步骤4:编写测试类

 

package com.czxy;

import com.czxy.mp.MybatisPlusApplication;
import com.czxy.mp.domain.Customer;
import com.czxy.mp.mapper.CustomerMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.List;

/**

  • Created by 爱吃豆的土豆
    */
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = MybatisPlusApplication.class)
    public class TestDemo01 {
    @Resource
    private CustomerMapper customerMapper;

    @Test
    public void testFindAll() {
    List list = customerMapper.selectList(null);
    list.forEach(System.out::println);
    }
    }



## 3,基本操作


### 3.1:最的常见API


BaseMapper 封装CRUD操作,泛型 `T` 为任意实体对象


![](https://img-blog.csdnimg.cn/4a9833fd7187475f925520dc6b72c03d.png)


![](https://img-blog.csdnimg.cn/31877fc489e94425a827697ee4d81779.png)



@Test
public void testselectAll(){
    List<Customer> list = customerMapper.selectList(null);  //条件查询先传入条件为null
    for (Customer c : list) {
        System.out.println(c.toString());
    }
}

### 3.2:添加



@Test
public void insert(){
Customer customer = new Customer();
customer.setCname(“Nihao1”);
customer.setPassword(“1234”);
int i = customerMapper.insert(customer);
System.out.println(i);
}


**添加成功返回结果为1,添加失败返回结果为0,否则抛异常**


### 3.3:更新


* 通过id更新

 
@Test
public void testUpdate() {
    Customer customer = new Customer();
    customer.setCid(15);
    customer.setCname("测试777");
    customer.setPassword("777");

    // 需要给Customer设置@TableId
    customerMapper.updateById(customer);
}
* 更新所有

 
@Test
public void testUpdate2() {
    Customer customer = new Customer();
    customer.setCname("测试777");
    customer.setPassword("777");
    // 更新所有
    customerMapper.update(customer,null);
}


### 3.4:删除


* 根据id进行删除

 

@Test
public void testDelete() {
// 需要给Customer设置@TableId
int i = customerMapper.deleteById(11);
System.out.println(i);
}

* 批量删除

 

@Test
public void testBatchDelete() {
// 需要给Customer设置@TableId
int i = customerMapper.deleteBatchIds(Arrays.asList(9,10));
System.out.println(i);
}



## 4,查询


### 4.1:Map条件


**第一种没有放入任何条件查询:查询所有**



@Test
public void selectByMap(){
    //简单多条件查询 -使用map设置数据,依次eq查询(等值查询)
    HashMap<String, Object> map = new HashMap<>();
    List<Customer> customerList = customerMapper.selectByMap(map);
    for (Customer c : customerList) {
        System.out.println(c.toString());
    }
}

**第二种放入条件:按照条件进行查询**



@Test
public void selectByMap(){
    //简单多条件查询 -使用map设置数据,依次eq查询(等值查询)
    HashMap<String, Object> map = new HashMap<>();
    map.put("cname","jack");
    map.put("password","1234");
    List<Customer> customerList = customerMapper.selectByMap(map);
    for (Customer c : customerList) {
        System.out.println(c.toString());
    }
}

### 4.2:Wrapper条件


#### 4.2.1:wrapper介绍


首先先翻译一下wrapper (包装器),不知道大家有没有听过包装类,主要应用在一种模式上面叫装饰 设计模式 里面出现的其实就是包装类。


大家应该见过请求或者响应包装类:分别是


HttpServletRequestWrapper , HttpServletResponseWrapper 


![](https://img-blog.csdnimg.cn/f9289fc0ba2e4588931958c9d8914dfd.png)


 像现在在Mybatis-plus 中也用到了wrapper ,**它的意思就是把条件查询中的条件给它封装一下**


//结合idea向大家介绍一下


idea中  Shift + Ctrl + a  弹出来搜索框:


![](https://img-blog.csdnimg.cn/43cd4edcfac14001a178d7ca119f22e1.png)


 点进去wrapper中按CTRL + H  查看继承树


![](https://img-blog.csdnimg.cn/a2ba85f8ec1b4127b8024ba78734c277.png)


* Wrapper : 条件构造抽象类,最顶端父类


	+ AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
	
	
		- QueryWrapper : Entity 对象封装操作类,不是用lambda语法
		- UpdateWrapper : Update 条件封装,用于Entity对象更新操作
		- AbstractLambdaWrapper : Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。
		
		
			* LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询Wrapper
			* LambdaUpdateWrapper : Lambda 更新封装Wrapper
* **如果想进行复杂条件查询,那么需要使用条件构造器 Wapper,涉及到如下方法**


![](https://img-blog.csdnimg.cn/92a61a707b974826aacefcacf5c02df3.png)


* **拼凑条件相关关键字**


![](https://img-blog.csdnimg.cn/2b3d7bb2be6c41c2a0d1527d79cfad5d.png) ![](https://img-blog.csdnimg.cn/6c0a5a726ce34d3aa947cb49733345b3.png)


#### 4.2.2:条件查询(练习两个方法)


**注意:条件查询里面的条件,column 对应的是数据库中的列,而不是JavaBean中的属性**


**selectOne           根据条件查询一个,结果:0或者1,如果查询多个异常**


 三种情况:第一种情况:**查询成功一条数据  查询名称为rose的**


![](https://img-blog.csdnimg.cn/a4b660ff830249b9b9137573af1993dd.png)


 第二种情况:**查询失败,查询到了多个数据  查询名称为发大财,查询到两个**


![](https://img-blog.csdnimg.cn/f5f26ebe97904402b4c434652c48a1ef.png)


**抛出的异常信息(我用中文翻译一下哈哈):期望结果为一个或者为null,但是发现两个**


![](https://img-blog.csdnimg.cn/a634d2ba97fa426f8db807b27f7c9e59.png)


 第三种情况:**查询为null,不存在该条数据,查询名称大钱,返回结果为null数据库中没有该数据**


![](https://img-blog.csdnimg.cn/4022eb4192d74ac09bd36decd05a2ce4.png)


 再练习一个![](https://img-blog.csdnimg.cn/3e2aab407e664304a2e99e74b3b85041.png)


**模糊查询:like 。需要注意的是:之前在Mybatis中模糊查询需要自己手动加入%%**


**在Mybatis-plus中不需要进行添加在底层中已经进行封装**



@Test
public void TestSelectList(){
    QueryWrapper<Customer> queryWrapper = new QueryWrapper<>();
    //模糊查询

// queryWrapper.like(“cname”,“c”); //左右加入了%
// queryWrapper.likeLeft(“cname”,“c”); //左加入了%
// queryWrapper.likeRight(“cname”,“c”); //右加入了%
//范围查询 比如年龄大于19的小于20的
queryWrapper.ge(“age”,19);
queryWrapper.le(“age”,30);
List customerList = customerMapper.selectList(queryWrapper);
for (Customer c : customerList) {
System.out.println(c.toString());
}
}


#### 4.3.3:条件更新


测试一个更新:需求更新电话号码为626115的信息,将该数据的名称更新为爱吃豆的土豆


![](https://img-blog.csdnimg.cn/f3db2af0e8f54f6bb8ba48b3f7d25172.png)



@Test
public void testUpdate(){
Customer customer = new Customer(21, “爱吃豆子的土豆”, “123”, “123”, 1000.0, 0, null, null);
UpdateWrapper updateWrapper = new UpdateWrapper<>();
updateWrapper.eq(“telephone”,626115);
int update = customerMapper.update(customer, updateWrapper);
System.out.println(update);
}


![](https://img-blog.csdnimg.cn/4a3900d82de5483fa25a0ef7c2e32c6e.png)


 **控制台sql语句执行的流程建议多看看:**


![](https://img-blog.csdnimg.cn/44ca1838746d417f8f8fdf17770b20e4.png)


### 4.3:分页


#### 4.3.1:内置插件


* 主体插件: MybatisPlusInterceptor,该插件内部插件集:


	+ **分页插件: PaginationInnerInterceptor(这个怎么理解呢!就是Mybatis-plus提供的内置分页拦截器,就是从到数据库读数据之前,分页拦截器拦截下来,根据分页条件在该执行的sql语句后面加入条件判断)以用来达到我们想要的效果**
	+ 多租户插件: TenantLineInnerInterceptor
	+ 动态表名插件: DynamicTableNameInnerInterceptor
	+ **乐观锁插件: OptimisticLockerInnerInterceptor(后文介绍乐观锁插件)**
	+ sql性能规范插件: IllegalSQLInnerInterceptor
	+ 防止全表更新与删除插件: BlockAttackInnerInterceptor


#### 4.3.2:配置类(配置类可以去官网复制也可以在这里直接复制)



@Configuration
public class MybatisPlusConfig {

/**
 * 配置插件
 * @return
 */
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){

    MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
    // 分页插件
    mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

    return mybatisPlusInterceptor;
}

/**
 * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
 * @return
 */
@Bean
public ConfigurationCustomizer configurationCustomizer() {
    return configuration -> configuration.setUseDeprecatedExecutor(false);
}

}


![](https://img-blog.csdnimg.cn/30f4753c5f754f9fa66f6caa9f3af777.png)


#### 4.4.3:分页(**用的还是比较多的,应该多练习**)



@Test
public void testPage(){
    //条件查询条件
    QueryWrapper<Customer> queryWrapper = new QueryWrapper<Customer>();

// queryWrapper.le()
// queryWrapper.like()
//分页查询的条件
int current = 1; // 当前页,相当于pagenum
int size =2;
Page customerPage = new Page<>(current,size);
//分页查询
customerMapper.selectPage(customerPage,queryWrapper);
//处理结果
customerPage.getRecords().forEach(System.out::println);
//分页数据
System.err.println(“当前页码:” + customerPage .getCurrent());
System.err.println(“每页显示记录数:” + customerPage .getSize());
System.err.println(“总页数:” + customerPage .getPages());
System.err.println(“总记录数:” + customerPage .getTotal());
System.err.println(“是否有下一页:” + customerPage .hasNext());
System.err.println(“是否有上一页:” + customerPage .hasPrevious());
}


**另外注意一种情况 (当你发现分页信息都无效的时候),首先要考虑有没有配置分页拦截器**


![](https://img-blog.csdnimg.cn/dd16c0ecd8ca45c7bc59bb469cfc8302.png)


## 5,常见注解(主要给大家演示三个最常用的注解)


### 5.1:表名注解:@TableName


@TableName 里面属性还是很多的


![](https://img-blog.csdnimg.cn/d33a2f3ac6374461ac13a8d56ab68364.png)


**最常用的两种**![](https://img-blog.csdnimg.cn/b3d639aed0764c3498063c8a8afbf44a.png)


**(value属性)如果在该注解中只用到了一个属性值value,且是一对,则value可以省略:如果所示**


![](https://img-blog.csdnimg.cn/58249e3b17a74627a2183cf20445ea99.png)


**(keepGlobalPrefix属性)大家在以后的开发项目中,会发现一个项目中表都有固定的前缀,既然有前缀那我们就想一想能不能把这个前缀进行抽取出来,放到一个固定的位置,这个属性就起到了该作用:如图所示**


![](https://img-blog.csdnimg.cn/ada3a03880d04ce5a152429b7c3364cf.png)


![](https://img-blog.csdnimg.cn/092badeb9c9146f9b490e422b7afe5f5.png)



### 5.2:主键注解:@TableId


value主键名就不多说了,**主要说一下type主键类型,也称为主键生成策略**


![](https://img-blog.csdnimg.cn/57bd3f3d901f454694713888b0d92d1d.png)


**IdType.AUTO,自动增长:**


![](https://img-blog.csdnimg.cn/adc3b837238a44e785f252abe2434b59.png)


**IdType.ASSIGN\_UUID**


![](https://img-blog.csdnimg.cn/eb0c0eabb9d24a1799b3976852893d69.png)


**IdType.ASSIGN\_ID**


![](https://img-blog.csdnimg.cn/dbfc1150d7454c06819901a26ef1912b.png)


### 5.3:字段注解(非主键):@TableField


![](https://img-blog.csdnimg.cn/e81cc2a94f2144ba8f4ce282d923662f.png)


1,value:对应表中的列名称   
 2,fill(在目录(第7)高级中详细讲解)


![](https://img-blog.csdnimg.cn/e2e400ccd37146499611f5cb1853fb67.png)


**3,exist:设置是否存储到数据库中:**


**例如:以后在开发中我们要进行批量删除,为了满足需求我们创建了一个集合或者数组来接收前端传递过来的数据,但这个数据又需要写进数据库中,数据库中也没有对应的列。这样我们就可以用这个属性来控制是否写进数据库中。**


![](https://img-blog.csdnimg.cn/3fd1c1d7d47d488fbf7c535e5876c1fc.png)


**注意:Mybatis-plus 中默认一个JavaBean和一张表是一一对应的,如果JavaBean中多出一个成员变量,它就去表里面找对应的列,没有的话就报错,这样就可以用这个属性进行声明**


## 6,常见配置


讲一下配置在yml文件中**Mybatis-plus的常见配置**(我这里是springboot项目)



mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #输出日志
map-underscore-to-camel-case: true #驼峰命名
global-config:
db-config:
id-type: auto #全局配置,id自动增强
table-prefix: tmp_ #表名前缀
type-aliases-package: com.czxy.mp.domain #别名包扫描路径
mapper-locations: classpath*:/mapper/**/*.xml #映射文件位置


**日志介绍(给大家讲解了各种日志):**


![](https://img-blog.csdnimg.cn/2e192244f6004c58ba9e194453d4124f.png)


**开启驼峰(用图和大家解释):**


![](https://img-blog.csdnimg.cn/d2270485dc1844acb218ffe8b6fc7053.png)


**全局配置主键策略和全局配置表名的前缀 :**


![](https://img-blog.csdnimg.cn/b2ca9527695643118b16c72368f93041.png)


**xml相关配置,整合XML版本开发 (重要):**


![](https://img-blog.csdnimg.cn/879b6f5bc7754b108a75bc665695951d.png)


**mapper-locations: 就是mapper映射的XML文件位置(如下图)。因为经常用注解开发很少写XML版开发,所以不怎么写。**


![](https://img-blog.csdnimg.cn/5107d2e683f147a8a5de58b899f82611.png)


![](https://img-blog.csdnimg.cn/b126b6c504b0455b8283958c4e67a62e.png)


 type-aliases-package:这个应用场景打个比方就是,如果以后开发中你做了十几个查询功能,返回类型都是同一个,这样每一次都全部输入显得很麻烦,我们可以通过这个配置进行起别名操作。(详细讲解如图)


![](https://img-blog.csdnimg.cn/4a2251f0af5148b3a70afd1d74dbce47.png)


 


 XML文件中内容(官方模板):



<?xml version="1.0" encoding="UTF-8"?> ```

7,高级(插件机制)

7.1:自动填充

项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。

我们可以使用MyBatis Plus的自动填充功能,完成这些字段的赋值工作:

7.1.1:原理

  • 实现元对象处理器接口:com.baomidou.mybatisplus.core.handlers.MetaObjectHandler,确定填充具体操作

  • 注解填充字段:@TableField(fill = ...) 确定字段填充的时机

    • FieldFill.INSERT:插入填充字段
    • FieldFill.UPDATE:更新填充字段
    • FieldFill.INSERT_UPDATE:插入和更新填充字段
7.1.2:基本操作(实际操作和大家介绍一下)

解释一下:这个自动填充就是相当于为程序添加一个拦截器,当用户改变自己的信息的时候,拦截一下自动把更改的时间进行装填到数据库中。在以后工作中会经常用到

  • 步骤一:修改表添加字段:为表添加两个字段
alter table tmp_customer add column create_time date;
alter table tmp_customer add column update_time date;
  • 步骤二:修改JavaBean
package com.czxy.mp.domain;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;

import java.util.Date;

/**
 * Created by 爱吃豆的土豆.
 */
@Data
@TableName("tmp_customer")
public class Customer {
    @TableId(type = IdType.AUTO)
    private Integer cid;
    private String cname;
    private String password;
    private String telephone;
    private String money;

    @TableField(value="create_time",fill = FieldFill.INSERT)
    private Date createTime;

    @TableField(value="update_time",fill = FieldFill.UPDATE)
    private Date updateTime;

}
  • 步骤三:编写处理类  
package com.czxy.mp.handler;

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

import java.util.Date;

/**
 * @author 爱吃豆的土豆
 */
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    /**
     * 插入填充
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime", new Date(), metaObject);
    }

    /**
     * 更新填充
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}
  • 步骤四:测试
    @Test
    public void testInsert() {
        Customer customer = new Customer();
        customer.setCname("测试888");

        customerMapper.insert(customer);
    }

    @Test
    public void testUpdate() {
        Customer customer = new Customer();
        customer.setCid(11);
        customer.setTelephone("999");

        customerMapper.updateById(customer);
    }

7.2:乐观锁(主要讲一下乐观锁的版本号机制

  • 基于数据库

    • 乐观锁:数据不同步不会发生。读锁。
      乐观锁(Optimistic Lock), 顾名思义,**就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。**乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。
    • 悲观锁:数据不同步肯定发生。写锁。
      悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
7.2.1:什么是乐观锁
  • 目的:数据必须同步。当要更新一条记录的时候,希望这条记录没有被别人更新
  • 乐观锁实现方式:
  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败
7.2.2:实现
  • 步骤:

    • 步骤1:环境准备(表version字段、JavaBean versoin属性、必须提供默认值)
    • 步骤2:使用乐观锁版本控制 @Version
    • 步骤3:开启乐观锁插件配置
  • 步骤一:修改表结构,添加version字段

  • 步骤二:修改JavaBean,添加version属性
  • 步骤三:元对象处理器接口添加version的insert默认值 (保证version有数据)
package com.czxy.mp.config;

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

import java.util.Date;

/**
 * Created 爱吃豆的土豆.
 */
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    /**
     * 插入填充
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("version", 1, metaObject);
    }

    /**
     * 更新填充
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}
  • 步骤四:修改 MybatisPlusConfig 开启乐观锁
/**
 * Created 爱吃豆的土豆.
 */
@Configuration
public class MybatisPlusConfig {
     */
    /**
     * 配置插件
     * @return
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){

        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        // 分页插件
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        // 乐观锁
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

        return mybatisPlusInterceptor;
    }
}
  • 步骤五:测试

    • 先添加一条,保证version有数据
    • 在更新该条
    @Test
    public void testUpdate() {
        Customer customer = new Customer();
        customer.setCid(14);
        customer.setCname("测试999");
        // 与数据库中数据一致,将更新成功,否则返回失败。
        customer.setVersion(1);

        int i = customerMapper.updateById(customer);
        System.out.println(i);
    }
7.2.3:注意事项
  • 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • 整数类型下 newVersion = oldVersion + 1
  • newVersion 会回写到 entity
  • 仅支持 updateById(id)update(entity, wrapper) 方法
  • update(entity, wrapper) 方法下, wrapper 不能复用!!!
  • 数据库表的version字段,必须有默认值(SQL语句默认值、或MyBatisPlus自动填充)
  • 在进行更新操作时,必须设置version值,否则无效。

7.3:逻辑删除

7.3.1:什么是逻辑删除

逻辑删除,也称为假删除。就是在表中提供一个字段用于记录是否删除,实际该数据没有被删除。(像大部分用户信息,如果你联系客服让他注销的话,只是客观意义上找不到用户信息,实际上还是存在的,只是进行了逻辑删除。)

7.3.2:实现
  • 步骤:

    • 步骤一:环境(表提供字段deleted、JavaBean属性 deleted、填充默认值0)
    • 步骤二:修改JavaBean,添加注解 @TableLogic
  • 步骤一:修改表结构添加deleted字段

  • 步骤二:修改JavaBean,给deleted字段添加@TableLogic

/**
 * Created 爱吃豆的土豆.
 */
@Data
@TableName("tmp_customer")
public class Customer {
    @TableId(type = IdType.AUTO)
    private Integer cid;
    private String cname;
    private String password;
    private String telephone;
    private String money;
    @Version
    @TableField(fill = FieldFill.INSERT)
    private Integer version;

    @TableLogic
    @TableField(fill = FieldFill.INSERT)
    private Integer deleted;
}
  • 步骤三:添加数据时,设置默认“逻辑未删除值”
/**
 * Created 爱吃豆的土豆
 */
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    /**
     * 插入填充
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("version", 1, metaObject);
        this.setFieldValByName("deleted", 0, metaObject);
    }

    /**
     * 更新填充
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}
  • 步骤四:测试
  •   @Test
      public void testDelete() {
          // 删除时,必须保证deleted数据为“逻辑未删除值”
          int i = customerMapper.deleteById(12);
          System.out.println(i);
      }
    


#### 7.3.3:注意


* 如果使用逻辑删除,将delete语句,修改成了update,条件 where deleted=0
* 同时,查询语句自动追加一个查询条件 `WHERE deleted=0`。如果查询没有数据,检查deleted字段的值。


#### 7.3.4:全局配置


* 如果使用了全局配置,可以不使用注解`@TableLogic`

 

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



#### 7.3.5:恢复


* 问题:进行逻辑删除后的数据,如何恢复(recovery)?
* **方案1:使用sql具有,更新deleted=0即可**



> 
> UPDATE `tmp\_customer` SET `deleted`='0' WHERE `cid`='13';


![img](https://img-blog.csdnimg.cn/img_convert/58368bfd927135d884debee39a5a9179.png)
![img](https://img-blog.csdnimg.cn/img_convert/3178c51b697e5a8292a38f95e1af51c0.png)
![img](https://img-blog.csdnimg.cn/img_convert/a1660c423c6a321fc5eec0e38e944843.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**

tomerMapper.deleteById(12);
        System.out.println(i);
    }
7.3.3:注意
  • 如果使用逻辑删除,将delete语句,修改成了update,条件 where deleted=0
  • 同时,查询语句自动追加一个查询条件 WHERE deleted=0。如果查询没有数据,检查deleted字段的值。
7.3.4:全局配置
  • 如果使用了全局配置,可以不使用注解@TableLogic
mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted  # 局逻辑删除的实体字段名
      logic-delete-value: 1  # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
7.3.5:恢复
  • 问题:进行逻辑删除后的数据,如何恢复(recovery)?
  • 方案1:使用sql具有,更新deleted=0即可

UPDATE tmp\_customer SET deleted=‘0’ WHERE cid=‘13’;

[外链图片转存中…(img-Rv81z3uo-1715431233881)]
[外链图片转存中…(img-SSABaRZf-1715431233881)]
[外链图片转存中…(img-h6PmI0Wn-1715431233881)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

  • 16
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值