Mybatis plus -- extension -- use / tutorial / example

Keywords: mybatis-plus MybatisPlus

Original website: Mybatis plus -- extension -- use / tutorial / example_ CSDN blog

brief introduction

brief introduction

        This paper introduces the common extended functions of MybatisPlus, including logical deletion, automatic filling and performance analysis.

Official website

https://baomidou.com/guide/logic-delete.html# usage method

Logical deletion

brief introduction

        Deletion is a common requirement in a project. For example, you need to delete a commodity or an order, but you often choose logical deletion instead of deleting the actual data. There is an is in the general table_ The deleted field indicates whether the user has been deleted. 0 means it has not been deleted   1 means deleted.

Configuration (optional)

Configure the status codes identified by undeleted and deleted, and the yml format is adopted here.

mybatis-plus:
  global-config:
    db-config:
      # 1 means deleted. The default is 1. It can also be written as a field name, such as id. when deleting, the value of id will be written to the logically deleted field
      logic-delete-value: 1
      # 0 means not deleted. The default is 0
      logic-not-delete-value: 0

Global configuration field name (optional)

        If the project code is relatively standard and the logical deletion fields of all tables use the same name (such as deleted_flag), we can   application.properties   Add the following unified configuration to the corresponding entity class field, so that you don't need to add it again  @ TableLogic   Notes:

        Note: if the global logical deletion field value is set, there are still fields on the entity class  @ TableLogic   The on the entity shall prevail and the global shall be ignored.

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted_flag

entity

Annotate @ TableLogic on the field corresponding to the entity class

@Data
@TableName("tb_user")
public class User extends Model<User> implements Serializable {
 
    private static final long serialVersionUID=1L;
 
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
 
    @TableLogic
    private String deleted;
}

database

  Database deleted column, set to tinyint type, length 1

Insert test

When inserting, the sql statement does not involve logically deleted fields.

Query, modify and test

After the MP logical deletion function is used, the query and modification methods are executed, and MP will automatically add undeleted conditions for us. Except custom sql

    @Test
    public void select(){
        List<User> users = userMapper.selectList(Wrappers.<User>lambdaQuery().eq(User::getAge, 18));
        users.forEach(System.out::println);
    }
 
    @Test
    public void update(){
        User user = new User();
        user.setEmail("Test@email.com");
        
        int update = userMapper.update(user, Wrappers.<User>lambdaQuery().eq(User::getAge, 18));
        System.out.println(update);
    }
DEBUG==>  Preparing: SELECT id,login_name,name,password,email,salt,sex,age,phone,user_type,status,organization_id,create_time,is_delete FROM sys_user WHERE deleted='0' AND age = ? 
DEBUG==> Parameters: 18(Integer)
DEBUG<==      Total: 0
 
 
DEBUG==>  Preparing: UPDATE sys_user SET email=? WHERE deleted='0' AND age = ? 
DEBUG==> Parameters: Test@email.com(String), 18(Integer)
DEBUG<==    Updates: 0

Delete test

(the SQL statement executed is UPDATE)

    @Test
    public void delete() {
        int i = userMapper.deleteById(1);
        System.out.println(i);
    }
DEBUG==>  Preparing: UPDATE sys_user SET is_delete='1' WHERE id=? AND deleted='0' 
DEBUG==> Parameters: 1(Integer)
DEBUG<==    Updates: 1

Do not query is_deleted field

    @ TableField(select = false). You can also use the Wrapper's select expression to exclude some query fields, but it is more convenient through annotation.

    @TableLogic
    @TableField(select = false)
    private String deleted;

Auto fill

scene

        During data warehousing, whether adding or modifying data, you must manually set the addition time and modification time. Each insert needs to be set, and the database setting cannot be empty, which is very troublesome.
        Although you can set the default value in the database, if you do not have the permission to modify the database table, you can solve this problem technically. (if you have permission to modify database tables, you can directly set the corresponding field properties).

Failure condition

Case 1: use custom sql (statements written with @ Update() above Mapper's method)

Solution: in the method corresponding to custom sql, pass an additional time parameter.

entity

In the entity class field, you can set what operations to fill in by annotation. There are three types: add, update and delete.

of course

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

    // Insert and update both write this field. If FieldFill.UPDATE is used, this field is written only when updating.
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;

handler (recommended writing method)

        If some database tables do not have creation time and modification time fields, you can judge whether there is a setter if these operations are a bit wasteful.

        In versions 3.3.2 and later, this function already exists, while in previous versions, manual judgment is required.  

Mybatis plus 3.3.2 and later

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;

@Configuration
//@MapperScan("com.example.**.mapper")
public class MyBatisPlusConfig {
    private static final Logger logger = LoggerFactory.getLogger(MyBatisPlusConfig.class);

    //Auto fill plug-in
    @Bean
    public MetaObjectHandler metaObjectHandler() {
        return new MybatisPlusAutoFillConfig();
    }

    public static class MybatisPlusAutoFillConfig implements MetaObjectHandler {
        // Fill in when adding
        @Override
        public void insertFill(MetaObject metaObject) {
            logger.info("Inserting: autofill createTime and updateTime: "+ LocalDateTime.now());
            setFieldValByName("createTime", LocalDateTime.now(), metaObject);
            setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        }

        // Fill on modification
        @Override
        public void updateFill(MetaObject metaObject) {
            logger.info("Updating: autofill updateTime:" + LocalDateTime.now());
            setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        }
    }
}

  You can also write the configuration file like this  

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

import java.time.LocalDateTime;

@Component
public class MybatisPlusAutoFillConfig implements MetaObjectHandler {
    private static final Logger logger= LoggerFactory.getLogger(MybatisPlusAutoInjectConfig.class);

    // Fill in when adding
    @Override
    public void insertFill(MetaObject metaObject) {
        logger.info("Inserting: autofill createTime and updateTime: "+ LocalDateTime.now());
        boolean hasCreateTimeSetter = metaObject.hasSetter("createTime");
        Object createTime = getFieldValByName("createTime", metaObject);
        if (hasCreateTimeSetter) {
            // The first parameter corresponds to the entity attribute name, and the second parameter needs to fill in the value
            setInsertFieldValByName("createTime", LocalDateTime.now(), metaObject);
        }

        boolean hasupdateTimeSetter = metaObject.hasSetter("updateTime");
        Object updateTime = getFieldValByName("updateTime", metaObject);
        if (hasupdateTimeSetter) {
            // The first parameter corresponds to the entity attribute name, and the second parameter needs to fill in the value
            setUpdateFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        }
    }

    // Fill on modification
    @Override
    public void updateFill(MetaObject metaObject) {
        logger.info("Updating: autofill updateTime:" + LocalDateTime.now());
        boolean hasSetter = metaObject.hasSetter("updateTime");
        Object updateTime = getFieldValByName("updateTime", metaObject);
        if (hasSetter) {
            // The first parameter corresponds to the entity attribute name, and the second parameter needs to fill in the value
            setUpdateFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        }
    }
}

Mybatis plus before 3.3.2

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;

@Configuration
//@MapperScan("com.example.**.mapper")
public class MyBatisPlusConfig {
    private static final Logger logger = LoggerFactory.getLogger(MyBatisPlusConfig.class);

    //Auto fill plug-in
    @Bean
    public MetaObjectHandler metaObjectHandler() {
        return new MybatisPlusAutoFillConfig();
    }

    public static class MybatisPlusAutoFillConfig implements MetaObjectHandler {
        // Fill in when adding
        @Override
        public void insertFill(MetaObject metaObject) {
            logger.info("Inserting: autofill createTime and updateTime: "+ LocalDateTime.now());
            setFieldValByName("createTime", LocalDateTime.now(), metaObject);
            setUpdateFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        }

        // Fill on modification
        @Override
        public void updateFill(MetaObject metaObject) {
            logger.info("Updating: autofill updateTime:" + LocalDateTime.now());
            setUpdateFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        }
    }
}

You can also write the configuration file like this  

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

import java.time.LocalDateTime;

@Component
public class MybatisPlusAutoFillConfig implements MetaObjectHandler {
    private static final Logger logger= LoggerFactory.getLogger(MybatisPlusAutoInjectConfig.class);

    // Fill in when adding
    @Override
    public void insertFill(MetaObject metaObject) {
        logger.info("Inserting: autofill createTime and updateTime: "+ LocalDateTime.now());
        boolean hasCreateTimeSetter = metaObject.hasSetter("createTime");
        Object createTime = getFieldValByName("createTime", metaObject);
        if (hasCreateTimeSetter) {
            // The first parameter corresponds to the entity attribute name, and the second parameter needs to fill in the value
            setInsertFieldValByName("createTime", LocalDateTime.now(), metaObject);
        }

        boolean hasupdateTimeSetter = metaObject.hasSetter("updateTime");
        Object updateTime = getFieldValByName("updateTime", metaObject);
        if (hasupdateTimeSetter) {
            // The first parameter corresponds to the entity attribute name, and the second parameter needs to fill in the value
            setUpdateFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        }
    }

    // Fill on modification
    @Override
    public void updateFill(MetaObject metaObject) {
        logger.info("Updating: autofill updateTime:" + LocalDateTime.now());
        boolean hasSetter = metaObject.hasSetter("updateTime");
        Object updateTime = getFieldValByName("updateTime", metaObject);
        if (hasSetter) {
            // The first parameter corresponds to the entity attribute name, and the second parameter needs to fill in the value
            setUpdateFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        }
    }
}

handler (not recommended)

Because if updateTime is not null, updateTime will not be updated, which is not applicable to the case of finding out the data modification before writing

package com.example.base.config;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;
 
@Configuration
//@MapperScan("com.example.**.mapper")
public class MyBatisPlusConfig {
    private static final Logger logger = LoggerFactory.getLogger(MyBatisPlusConfig.class);
 
    //Auto fill plug-in
    @Bean
    public MetaObjectHandler metaObjectHandler() {
        return new MybatisPlusAutoFillConfig();
    }
 
    public static class MybatisPlusAutoFillConfig implements MetaObjectHandler {
        // Fill in when adding
        @Override
        public void insertFill(MetaObject metaObject) {
            logger.info("Inserting: autofill createTime and updateTime: "+ LocalDateTime.now());

            this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // Starting version 3.3.0 (recommended)
            this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // Starting version 3.3.0 (recommended)
            // perhaps
            // this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); //  Starting version 3.3.3 (recommended)
            // this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); //  Starting version 3.3.3 (recommended)
        }
 
        // Fill on modification
        @Override
        public void updateFill(MetaObject metaObject) {
            logger.info("Updating: autofill updateTime:" + LocalDateTime.now());
            this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // Starting version 3.3.0 (recommended)
            // perhaps
            // this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); //  Starting version 3.3.3 (recommended)        
        }
    }
}

performance analysis

Other web sites

Mybatis plus official website

brief introduction

This function depends on   p6spy   Component, perfect output, print SQL and execution time   3.1.0   Above version  

rely on

<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>Latest version</version>
</dependency>

application.yml

spring:
  datasource:
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver
    url: jdbc:p6spy:h2:mem:test
    ...

spy.properties

#3.2.1 use of the above
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1 the following are used or not configured:
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# Custom log printing
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#Log output to console
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# Use the logging system to record sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# Set p6spy driver agent
deregisterdrivers=true
# Remove JDBC URL prefix
useprefix=true
# Log exceptions are configured. The result sets that can be removed include error,info,batch,debug,statement,commit,rollback,result,resultset
excludecategories=info,debug,result,commit,resultset
# Date format
dateformat=yyyy-MM-dd HH:mm:ss
# The actual drive can be multiple
#driverlist=org.h2.Driver
# Enable slow SQL logging
outagedetection=true
# Slow SQL record standard 2 seconds
outagedetectioninterval=2

be careful

  • Driver class name is the p6spy provided driver class
  • The url prefix is jdbc:p6spy followed by a colon as the corresponding database connection address
  • Print out that the sql is null, and add commit in excludecategories
  • Batch operation does not print sql, and batch in excludecategories is removed
  • Please use mybatispluslogfactory (new in 3.2.1) to print duplicate problems in batch operation
  • The plug-in has performance loss and is not recommended for production environment.

Other web sites

Mybatis plus _bitch _itbitch CSDN blog

Mybatis plus advanced function - realize logical deletion bitch - CSDN blog _mybaitisplusisdelete

Posted by TheTechChik on Thu, 11 Nov 2021 17:21:25 -0800