MyBatis-Plus--Solve the problem of logical deletion and unique index--method/example

Original URL: MyBatis-Plus--Solving the Problem of Logical Deletion and Unique Index--Method/Example

Introduction

illustrate

This article uses an example to introduce how MyBatis-Plus solves the problem of logical deletion and unique index.

Physical deletion and logical deletion

        Data is very important, and the data in the database is generally not physically deleted directly with the DELETE statement when it is deleted.

        The usual practice is to use logical deletion, that is, to add a new field to mark whether to delete it, it is not really deleted when it is deleted, but an UPDATE statement is used to set a field to be deleted. For example: "deleted_flag", 0 means not deleted, other means deleted.

MyBatis-Plus default tombstone deletion

In MyBatis-Plus, a field can be marked as a tombstone field by adding the @TableLogic annotation to the field:

@TableLogic
private Long deletedFlag;

This way, when manipulating the data, it automatically does:

When querying: automatically add "AND deletedFlag = 0"

When deleting: UPDATE SET deletedFlag = 1 ... WHERE ... AND deleted_flag = 0

The corresponding default configuration is:

mybatis-plus:
  global-config:
    db-config:
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

MyBatis-Plus default tombstone problem

        Suppose there is a user table with user_name and deleted_flag fields, and you want to add a unique index to user_name (to improve the query speed and ensure that the user name is not repeated), then there are the following two solutions:

  1. set user_name as unique index
    1. This is not acceptable. For example, if a user named "Tony" is deleted, and another user is registered as "Tony", an error will be reported. The error message is this: Duplicate entry 'Tony' for key 't_user.index_user_name'
  2. set user_name and deleted_flag to the joint unique index
    1. This is also not possible, for example:
      1. There was a user named "Tony", which was deleted so that the joint index was "Tony-1".
      2. Another user is registered, registered as "Tony", this will not report an error, at this time the joint index of the new user is "Tony-0"
      3. If the new user is deleted, an error will be reported: because the joint index of the new user is "Tony-1" at this time, the database already exists. The error message is this: Duplicate entry 'Tony-1' for key 't_user.index_user_name_deleted_flag'

Problem recurrence

rely

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
<!--        <version>2.0.0.RELEASE</version>-->
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>MyBatis-Plus_Simple</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>MyBatis-Plus_Simple</name>
    <description>Demo project for Spring Boot</description>

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

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

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>

    </dependencies>

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

</project>

Build a database and build a table

DROP DATABASE IF EXISTS mp;
CREATE DATABASE mp DEFAULT CHARACTER SET utf8;
USE mp;

DROP TABLE IF EXISTS `t_user`;
SET NAMES utf8mb4;

CREATE TABLE `t_user`
(
    `id`              BIGINT(0) NOT NULL AUTO_INCREMENT,
    `user_name`       VARCHAR(64) NOT NULL COMMENT '用户名(不能重复)',
    `nick_name`       VARCHAR(64) NULL COMMENT '昵称(可以重复)',
    `email`           VARCHAR(64) COMMENT '邮箱',
    `create_time`  DATETIME(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_time` DATETIME(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    `deleted_flag` BIGINT(0) NOT NULL DEFAULT 0 COMMENT '0:未删除 其他:已删除',
    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE KEY `index_user_name_deleted_flag` (`user_name`, `deleted_flag`),
    KEY `index_create_time`(`create_time`)
) ENGINE = InnoDB COMMENT = '用户';

INSERT INTO `t_user` VALUES (1, 'knife', '刀刃', '[email protected]', '2021-01-23 09:33:36', '2021-01-23 09:33:36', 0);
INSERT INTO `t_user` VALUES (2, 'sky', '天蓝', '[email protected]', '2021-01-24 18:12:21', '2021-01-24 18:12:21', 0);

code

Entity

package com.example.demo.user.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;

import java.time.LocalDateTime;

@Data
@TableName(value = "t_user")
public class User {
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    /**
     * 用户名(不能重复)
     */
    private String userName;

    /**
     * 昵称(可以重复)
     */
    private String nickName;

    /**
     * 邮箱
     */
    private String email;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 修改时间
     */
    private LocalDateTime updateTime;

    /**
     * 0:未删除 其他:已删除
     */
    @TableLogic
    private Long deletedFlag;
}

Service

interface

package com.example.demo.user.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.user.entity.User;

public interface UserService extends IService<User> {
}

Implementation class

package com.example.demo.user.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.user.entity.User;
import com.example.demo.user.mapper.UserMapper;
import com.example.demo.user.service.UserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

Controller

package com.example.demo.user.controller;

import com.example.demo.user.entity.User;
import com.example.demo.user.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Api(tags = "测试")
@RestController
@RequestMapping("test")
public class TestController {

    @Autowired
    private UserService userService;

    @ApiOperation("删除")
    @PostMapping("delete")
    public String delete(Long id) {
        userService.removeById(id);
        return "remove success";
    }

    @ApiOperation("添加")
    @PostMapping("add")
    public User add() {
        User user = new User();
        user.setUserName("sky");
        userService.save(user);
        return user;
    }
}

test

Open the test page: http://localhost:8080/doc.html

1. View raw data

2. Delete the data whose user_name is "sky"

Database results (successfully deleted)

backend result

==>  Preparing: UPDATE t_user SET deleted_flag=1 WHERE id=? AND deleted_flag=0 
==> Parameters: 2(Long)
<==    Updates: 1

3. Add data with user_name "sky"

Database result (add successfully)

Backend result (add successfully)

==>  Preparing: INSERT INTO t_user ( user_name ) VALUES ( ? ) 
==> Parameters: sky(String)
<==    Updates: 1

4. Delete the data whose user_name is "sky"

Database results (delete failed)

Backend result (delete failed)

2022-03-20 16:46:09.895 ERROR 15904 --- [nio-8080-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DuplicateKeyException: 
### Error updating database.  Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'sky-1' for key 't_user.index_user_name_deleted_flag'
### The error may exist in com/example/demo/user/mapper/UserMapper.java (best guess)
### The error may involve com.example.demo.user.mapper.UserMapper.deleteById-Inline
### The error occurred while setting parameters
### SQL: UPDATE t_user SET deleted_flag=1 WHERE id=?  AND deleted_flag=0
### Cause: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'sky-1' for key 't_user.index_user_name_deleted_flag'
; Duplicate entry 'sky-1' for key 't_user.index_user_name_deleted_flag'; nested exception is java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'sky-1' for key 't_user.index_user_name_deleted_flag'] with root cause

java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'sky-1' for key 't_user.index_user_name_deleted_flag'
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117) ~[mysql-connector-java-8.0.20.jar:8.0.20]
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) ~[mysql-connector-java-8.0.20.jar:8.0.20]
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-java-8.0.20.jar:8.0.20]
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953) ~[mysql-connector-java-8.0.20.jar:8.0.20]
	at com.mysql.cj.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:370) ~[mysql-connector-java-8.0.20.jar:8.0.20]
	at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44) ~[HikariCP-3.4.5.jar:na]
	at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.execute(HikariProxyPreparedStatement.java) ~[HikariCP-3.4.5.jar:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201]
	at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:59) ~[mybatis-3.5.4.jar:3.5.4]
	at com.sun.proxy.$Proxy110.execute(Unknown Source) ~[na:na]
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:47) ~[mybatis-3.5.4.jar:3.5.4]
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74) ~[mybatis-3.5.4.jar:3.5.4]
	at com.baomidou.mybatisplus.core.executor.MybatisSimpleExecutor.doUpdate(MybatisSimpleExecutor.java:54) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
	at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) ~[mybatis-3.5.4.jar:3.5.4]
	at com.baomidou.mybatisplus.core.executor.MybatisCachingExecutor.update(MybatisCachingExecutor.java:83) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
	at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:197) ~[mybatis-3.5.4.jar:3.5.4]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201]
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:426) ~[mybatis-spring-2.0.4.jar:2.0.4]
	at com.sun.proxy.$Proxy72.update(Unknown Source) ~[na:na]
	at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:287) ~[mybatis-spring-2.0.4.jar:2.0.4]
	at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:65) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:96) ~[mybatis-plus-core-3.3.2.jar:3.3.2]
	at com.sun.proxy.$Proxy77.deleteById(Unknown Source) ~[na:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201]
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at com.sun.proxy.$Proxy78.deleteById(Unknown Source) ~[na:na]
	at com.baomidou.mybatisplus.extension.service.IService.removeById(IService.java:104) ~[mybatis-plus-extension-3.3.2.jar:3.3.2]
	at com.baomidou.mybatisplus.extension.service.IService$$FastClassBySpringCGLIB$$f8525d18.invoke(<generated>) ~[mybatis-plus-extension-3.3.2.jar:3.3.2]
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:687) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at com.example.demo.user.service.impl.UserServiceImpl$$EnhancerBySpringCGLIB$$328c22ac.removeById(<generated>) ~[classes/:na]
	at com.example.demo.user.controller.TestController.delete(TestController.java:26) ~[classes/:na]
	...
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_201]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.36.jar:9.0.36]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_201]

solution

The source code of the @TableLogic annotation is as follows:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.baomidou.mybatisplus.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableLogic {
    String value() default "";

    String delval() default "";
}
  • value: Indicates the normal value of the delete marker field (the value when it is not deleted). Default is 0
  • delval: Indicates the value at the time of deletion of the deletion marker field (the value after deletion). Default is 1

So the method is: set delval to a value that will not conflict, for example:

  1. set delval to: "id"
    1. This will set deleted_flag to the value of id when deleting
  2. Set delval to: "NOW()"
    1. This will set deleted_flag to the time of deletion when deleting

illustrate

        The string specified by delval will be directly used as the SET value of the UPDATE statement. For example, if I specify delval as "abc", the statement when deleting is: UPDATE SET deleted_flag = abc WHERE ...

Option 1: Set field to id (recommended)

Program introduction

On delete will set the tombstone field to the value of id.

Build a database and build a table

DROP DATABASE IF EXISTS mp;
CREATE DATABASE mp DEFAULT CHARACTER SET utf8;
USE mp;

DROP TABLE IF EXISTS `t_user`;
SET NAMES utf8mb4;

CREATE TABLE `t_user`
(
    `id`              BIGINT(0) NOT NULL AUTO_INCREMENT,
    `user_name`       VARCHAR(64) NOT NULL COMMENT '用户名(不能重复)',
    `nick_name`       VARCHAR(64) NULL COMMENT '昵称(可以重复)',
    `email`           VARCHAR(64) COMMENT '邮箱',
    `create_time`  DATETIME(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_time` DATETIME(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    `deleted_flag` BIGINT(0) NOT NULL DEFAULT 0 COMMENT '0:未删除 其他:已删除',
    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE KEY `index_user_name_deleted_flag` (`user_name`, `deleted_flag`),
    KEY `index_create_time`(`create_time`)
) ENGINE = InnoDB COMMENT = '用户';

INSERT INTO `t_user` VALUES (1, 'knife', '刀刃', '[email protected]', '2021-01-23 09:33:36', '2021-01-23 09:33:36', 0);
INSERT INTO `t_user` VALUES (2, 'sky', '天蓝', '[email protected]', '2021-01-24 18:12:21', '2021-01-24 18:12:21', 0);

Modify Entity

package com.example.demo.user.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;

import java.time.LocalDateTime;

@Data
@TableName(value = "t_user")
public class User {
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    /**
     * 用户名(不能重复)
     */
    private String userName;

    /**
     * 昵称(可以重复)
     */
    private String nickName;

    /**
     * 邮箱
     */
    private String email;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 修改时间
     */
    private LocalDateTime updateTime;

    /**
     * 0:未删除 其他:已删除
     */
    @TableLogic(delval = "id")
    private Long deletedFlag;
}

test

Open the test page: http://localhost:8080/doc.html

1. View raw data

2. Delete the data whose user_name is "sky"

Database results (successfully deleted)

Backend result (successfully deleted)

==>  Preparing: UPDATE t_user SET deleted_flag=id WHERE id=? AND deleted_flag=0 
==> Parameters: 2(Long)
<==    Updates: 1

3. Add data with user_name "sky"

Database result (add successfully)

 Backend result (add successfully)

==>  Preparing: INSERT INTO t_user ( user_name ) VALUES ( ? ) 
==> Parameters: sky(String)
<==    Updates: 1

4. Delete the data whose user_name is "sky"

Database result (delete successful)

Backend result (delete successful)

==>  Preparing: UPDATE t_user SET deleted_flag=id WHERE id=? AND deleted_flag=0 
==> Parameters: 3(Long)
<==    Updates: 1

Scenario 2: Set field to current time (not recommended)

Program introduction

The tombstone field is set to the value of the NOW() function upon deletion.

Build a database and build a table

DROP DATABASE IF EXISTS mp;
CREATE DATABASE mp DEFAULT CHARACTER SET utf8;
USE mp;

DROP TABLE IF EXISTS `t_user`;
SET NAMES utf8mb4;

CREATE TABLE `t_user`
(
    `id`              BIGINT(0) NOT NULL AUTO_INCREMENT,
    `user_name`       VARCHAR(64) NOT NULL COMMENT '用户名(不能重复)',
    `nick_name`       VARCHAR(64) NULL COMMENT '昵称(可以重复)',
    `email`           VARCHAR(64) COMMENT '邮箱',
    `create_time`  DATETIME(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_time` DATETIME(0) NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
    `deleted_flag` DATETIME(0) NULL DEFAULT NULL COMMENT 'null:未删除 其他:已删除',
    PRIMARY KEY (`id`) USING BTREE,
    UNIQUE KEY `index_user_name_deleted_flag` (`user_name`, `deleted_flag`),
    KEY `index_create_time`(`create_time`)
) ENGINE = InnoDB COMMENT = '用户';

INSERT INTO `t_user` VALUES (1, 'knife', '刀刃', '[email protected]', '2021-01-23 09:33:36', '2021-01-23 09:33:36', null);
INSERT INTO `t_user` VALUES (2, 'sky', '天蓝', '[email protected]', '2021-01-24 18:12:21', '2021-01-24 18:12:21', null);

Modify Entity

package com.example.demo.user.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;

import java.time.LocalDateTime;

@Data
@TableName(value = "t_user")
public class User {
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    /**
     * 用户名(不能重复)
     */
    private String userName;

    /**
     * 昵称(可以重复)
     */
    private String nickName;

    /**
     * 邮箱
     */
    private String email;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 修改时间
     */
    private LocalDateTime updateTime;

    /**
     * NULL:未删除 其他:已删除
     */
    @TableLogic(value = "NULL", delval = "NOW()")
    private LocalDateTime deletedFlag;
}

test

 Open the test page: http://localhost:8080/doc.html

1. View raw data

2. Delete the data whose user_name is "sky"

Database results (successfully deleted)

Backend result (successfully deleted)

==>  Preparing: UPDATE t_user SET deleted_flag=NOW() WHERE id=? AND deleted_flag IS NULL 
==> Parameters: 2(Long)
<==    Updates: 1

3. Add data with user_name "sky"

Database result (add successfully)

Backend result (add successfully)

==>  Preparing: INSERT INTO t_user ( user_name ) VALUES ( ? ) 
==> Parameters: sky(String)
<==    Updates: 1

4. Delete the data whose user_name is "sky"

Database result (delete successful)

Backend result (delete successful)

==>  Preparing: UPDATE t_user SET deleted_flag=NOW() WHERE id=? AND deleted_flag IS NULL 
==> Parameters: 3(Long)
<==    Updates: 1

Guess you like

Origin blog.csdn.net/feiying0canglang/article/details/123586766