Mybatis plus learning notes (for details)

1, Introduction to MybatisPlus

MyBatis plus (opens new window) (MP for short) is an enhancement tool of MyBatis (opens new window). Based on MyBatis, it only makes enhancement without change, and is born to simplify development and improve efficiency. Mybatis plus Chinese document

characteristic:
1. No invasion: it is only enhanced without change, and its introduction will not affect the existing project, which is as smooth as silk
2. Low loss: the basic CURD will be injected automatically upon startup, with basically no loss of performance and direct object-oriented operation
3. Powerful crud operation: built in general Mapper and general Service, most CRUD operations of a single table can be realized only through a small number of configurations, and there is a powerful condition constructor to meet various use needs
4. Support calling in Lambda form: it is convenient to write various query conditions through Lambda expression, and there is no need to worry about wrong fields
5. Support automatic generation of primary key: support up to four primary key policies (including distributed unique ID generator - Sequence), which can be configured freely to perfectly solve the primary key problem
6. Support ActiveRecord mode: support ActiveRecord formal calls. Entity classes only need to inherit the Model class to perform powerful CRUD operations
7. Support custom global general operations: support global general method injection (Write once, use anywhere)
8. Built in code generator: code or Maven plug-in can be used to quickly generate Mapper, Model, Service and Controller layer code, support template engine, and have more custom configurations for you to use
9. Built in paging plug-in: Based on MyBatis physical paging, developers do not need to care about specific operations. After configuring the plug-in, writing paging is equivalent to ordinary List query
10. The paging plug-in supports multiple databases: MySQL, MariaDB, Oracle, DB2, H2, HSQL, SQLite, Postgre, SQLServer and other databases
11. Built in performance analysis plug-in: it can output SQL statements and their execution time. It is recommended to enable this function during development and testing to quickly find out slow queries
12. Built in global interception plug-in: it provides intelligent analysis and blocking of full table delete and update operations, and can also customize interception rules to prevent misoperation

Custom code generator MyCodeGenerator

Some steps in project construction are repetitive, such as creating an Entity according to the database table, and then creating its related Mapper, Mapper.xml, Service, Controller and other module files. These complicated and repeated steps are not beneficial to our programming. In order to liberate our hands and reduce these repetitive tasks, MP provides us with a code generator to help us quickly build the project structure.

To use the code generator, first import the following dependencies:

<!--Code generator dependency-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.4.1</version>
</dependency>

<!--Template engine dependency-->
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.0</version>
</dependency>

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

After the dependency import is completed, we need to write our own generator implementation. The following code can be adjusted according to your own needs. After modification, run the program.

public class MyCodeGenerator {
    public static void main(String[] args) {
        //1. Global configuration
        GlobalConfig globalConfig = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");//Current project directory
        globalConfig.setAuthor("wsl")             //author
                .setActiveRecord(true)  //Is AR mode supported
                .setOutputDir(projectPath + "/src/main/java")  //Build path
                .setFileOverride(false) //Overwrite
                .setIdType(IdType.AUTO) //Primary key policy
                .setServiceName("%sService")    //%s is the name of the Service interface used to generate prefixed with I
                .setBaseResultMap(true)
                .setBaseColumnList(true);

        //2. Data source configuration
        DataSourceConfig dbConfig = new DataSourceConfig();
        dbConfig.setDriverName("com.mysql.cj.jdbc.Driver")  //Set database driver
                .setUrl("jdbc:mysql://localhost:3306/mybatis?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2B8")
                .setUsername("root").setPassword("123456")
                .setDbType(DbType.MYSQL);   //Set database type

        //3. Policy configuration
        StrategyConfig strategyConfig = new StrategyConfig();
        // Auto fill configuration
        ArrayList<TableFill> tableFills = new ArrayList<>();
        TableFill updateTime = new TableFill("updateTime", FieldFill.INSERT_UPDATE);
        tableFills.add(updateTime);
        strategyConfig.setInclude("blog") //Generated table
                .setCapitalMode(true) //Global uppercase naming
                .setNaming(NamingStrategy.underline_to_camel)   //Naming strategy of database tables insinuating to entities
                .setEntityLombokModel(true)      //Automatic lombok
                .setLogicDeleteFieldName("deleted") //Logical deletion
                .setVersionFieldName("version") //Optimistic lock
                .setControllerMappingHyphenStyle(true)
//                .setRestControllerStyle(true)
                .setTableFillList(tableFills);   //Auto fill configuration

        //4. Package name policy configuration
        PackageConfig pkConfig = new PackageConfig();
        pkConfig.setParent("com.kuang") //Parent package
                .setMapper("mapper")
                .setService("service")
                .setController("controller")
                .setEntity("pojo")
                .setXml("mapper")
                .setModuleName("blog");


        //5. Integrated configuration
        AutoGenerator autoGenerator = new AutoGenerator();
        autoGenerator.setGlobalConfig(globalConfig)
                .setDataSource(dbConfig)
                .setStrategy(strategyConfig)
                .setPackageInfo(pkConfig);

        //6. Implementation
        autoGenerator.execute();
    }
}

Plug in configuration

Introduction to MP plug-in
1. PaginationInnerInterceptor
2. SQL execution analysis plug-in BlockAttackInnerInterceptor (malicious full table update and deletion by the organization)
3. Optimistic lock plug-in optisticlockerinnerinterceptor (when a record is to be updated, I hope it has not been updated by others)

MP integration SpringBoot

Integration dependence

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
 <dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-boot-starter</artifactId>
     <version>3.4.3.2</version>
 </dependency>

Environment configuration

# apply name
spring.application.name=mybatis_plus
# Application service WEB access port
server.port=8080
#Connection field
spring.datasource.username=root
spring.datasource.password=123456
# You need to set the time zone to use mysql version above 8.0
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

Entity class

package com.kuang.pojo;
import lombok.AllArgsConstructr;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
  private Integer id;
  private String name;
  private String pwd;
  private String perm;
}

Write mapper

package com.kuang.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.kuang.pojo.User;
import org.springframework.stereotype.Repository;
// Inherit the basic class BaseMapper on the corresponding Mapper
@Repository//Represents the persistence layer
public interface UserMapper extends BaseMapper<User> {
    //All CRUD operations have been written
    //You don't need to configure a lot of files as before!
}

Scan the mapper

package com.kuang;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("com.kuang.mapper")
@SpringBootApplication
public class MybatisPlus02Application {
    public static void main(String[] args) {
        SpringApplication.run(MybatisPlus02Application.class, args);
    }
}

Test query

package com.kuang;

import com.kuang.mapper.UserMapper;
import com.kuang.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.List
@SpringBootTest
class MybatisPlus02ApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {
        List<User> userList = userMapper.selectList(null);
        for (User user : userList) {
            System.out.println(user);
        }
    }
}

Optimistic lock handling

Optimistic lock: as the name suggests, it always thinks that there will be no problem. No matter what you do, don't lock it! If there is a problem, update the value test again!
Pessimistic lock: as the name suggests, it is very pessimistic. It always thinks that there are always problems. It will lock no matter what it does! Do it again!

Implementation of optimistic lock: first query the information of the object with version data (very important), then use it, and then modify it based on this object.
Example:
Annotate the version field

  @Version
  private Integer version;

Configure plug-ins and inject implementation.

@MapperScan("com.kuang.mapper")
@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {

    /**
     * new edition
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

After modification, the version field will be incremented automatically.

userMapper.updateById(user);

Possible problems of optimistic lock

  User user = userMapper.selectById(22);
  user.setName("Niu Niu");
  user.setPerm("1");

  //Simulate another thread queue jumping
  User user2 = userMapper.selectById(22);
  user2.setName("Niu Niu");
  user2.setPerm("2");

  userMapper.updateById(user2);
  userMapper.updateById(user);
  //The final result shows that only one version is added because the previous one is overwritten.

Logical deletion

When deleting table records in a database, we often use logical deletion, that is, changing the state of a record to limit it. Usually, a status field is added to each record, and 0 or 1 is used to represent its status (here it indicates whether to delete it). Using logical deletion also avoids the risk of losing important data.
MP provides us with automatic implementation of SQL statements of a series of operation tables. We can configure logical deletion through @ TableLogic.
Example:
Add the @ TableLogic annotation to the logically deleted field

 @TableLogic
 private Integer deleted;

Configure logically deleted fields and status values

# Global logically deleted entity field name (since 3.3.0, it can be ignored after configuration, and step 2 is not configured)
mybatis-plus.global-config.db-config.logic-delete-field=deleted
#Logical deleted value (default is 1)
mybatis-plus.global-config.db-config.logic-delete-value=1
# Logical undeleted value (0 by default)
mybatis-plus.global-config.db-config.logic-not-delete-value=0

After the configuration is successful, the deletion method of MP is used for logical deletion

userMapper.deleteById(22);

Note: the statements after logical deletion will not be queried by the mybatis plus method. You need to customize SQL to view them.

Log function

The log function of MP can view the generated SQL statements
Add logging support to the SpringBoot project

# Log output
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

Add logging support to the spring MVC project

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- Global parameters -->
    <settings>
        <!--Set log function-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
</configuration>

Auto fill field

When using MP to insert or add data, we can add some default fill values to it.
For example, the following automatically populates the creation time and update time of the object
1. Add @ TableField annotation on the field to be filled automatically, and set the fill property to FieldFill.INSERT or FieldFill.INSERT during insertion_ Update is populated when inserted or updated.

//Auto fill time on insertion
 @TableField(fill = FieldFill.INSERT)
 private Date createTime;
 //Auto fill time on insert or update
 @TableField(fill = FieldFill.INSERT_UPDATE)
 private Date updateTime;

2. Customize the implementation class of a meta object processor interface and inject it into the IOC container

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {

        this.strictInsertFill(metaObject, "createTime", 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)
        // perhaps
        this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // It can also be used (there is a bug in this method in 3.3.0)
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "modify_time", LocalDateTime.class, LocalDateTime.now()); // Starting version 3.3.0 (recommended)
        // perhaps
        this.strictUpdateFill(metaObject, "modity_time", () -> LocalDateTime.now(), LocalDateTime.class); // Starting version 3.3.3 (recommended)
        // perhaps
        this.fillStrategy(metaObject, "modity_time", LocalDateTime.now()); // It can also be used (there is a bug in this method in 3.3.0)
    }
}

The Spring project is assembled in the configuration file (the following steps can be omitted in the SpringBoot project)

<!-- Use here MP Provided sqlSessionFactory,It's done Spring And MP Integration of -->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
    <property name="plugins">
        <list>
            <!-- Register paging plug-in -->
            <bean class="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"></bean>
        </list>
    </property>
    <property name="globalConfig" ref="globalConfig"/>
</bean>

<!--Configure automatic injection time class-->
<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
    <property name="metaObjectHandler">
        <bean class="com.zktr.handler.MyMetaObjectHandler"/>
    </property>
</bean>

Keywords: mybatis-plus

Added by derekbelcher on Wed, 17 Nov 2021 11:51:59 +0200