Introduction summary of mybatis plus

Posted by php1 on Sun, 30 Jan 2022 07:49:04 +0100

1. Why learn MyBatisPlus?

  1. It can save us a lot of time
  2. All crud code can be generated automatically
  3. JPA, TK mapper and MyBatisPuls can automatically generate CRUD

2. Introduction to mybatis

Official website: https://baomidou.com/guide/

MyBatis-Plus (opens new window) (MP) is a MyBatis (opens new window) On the basis of MyBatis, the enhancement tool is only enhanced without change, and is born to simplify development and improve efficiency.

characteristic

  • No invasion: it is only enhanced without change, and its introduction will not affect the existing project, which is as smooth as silk
  • Low loss: the basic CURD will be injected automatically upon startup, with basically no loss of performance and direct object-oriented operation
  • 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. There is also a powerful condition constructor to meet various use needs
  • Support Lambda form call: through Lambda expression, it is convenient to write various query conditions without worrying about wrong fields
  • Support automatic generation of primary key: support up to 4 primary key strategies (including distributed unique ID generator - Sequence), which can be configured freely to perfectly solve the problem of primary key
  • Support ActiveRecord mode: support ActiveRecord formal calls. Entity classes only need to inherit Model classes to perform powerful CRUD operations
  • Support custom global general operations: support global general method injection (Write once, use anywhere)
  • 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
  • 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
  • The paging plug-in supports multiple databases: MySQL, MariaDB, Oracle, DB2, H2, HSQL, SQLite, Postgre, SQLServer and other databases
  • 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
  • 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

3.MybatisPlus quick start

1. Add data

DROP TABLE IF EXISTS user;

CREATE TABLE user
(
	id BIGINT(20) NOT NULL COMMENT 'Primary key ID',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT 'full name',
	age INT(11) NULL DEFAULT NULL COMMENT 'Age',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT 'mailbox',
	PRIMARY KEY (id)
);

-- implement SQL script

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

2. Initialization project

have access to Spring lnitializer Quickly initialize a Spring Boot engineering

3. Add dependency

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

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

        <!--add to mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>

        <!--add to mysql rely on-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

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

    </dependencies>

4. Write entity class

package com.xjggb.entity;
import lombok.Data;
@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

5. Write Mapper interface

package com.xjggb.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xjggb.entity.User;
/*
* If you don't want to add package scanning in the startup class, you can add this annotation @ Repository / / to represent the persistence layer
* CRUD function has been implemented
* */
public interface UserMapper extends BaseMapper<User> {
}

6. Write the service business layer

import com.xjggb.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServlce {
    @Autowired
    private UserMapper userMapper;

    /*
    * Query all data
    * */
    public List<User> selectList(){
        return userMapper.selectList(null);
    }
}

7. Write controller layer

package com.xjggb.controller;

import com.xjggb.entity.User;
import com.xjggb.service.UserServlce;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
@RestController
public class UserCotroller {
    @Autowired
    private UserServlce userServlce;

    /*
    * Query all data
    * */
    @GetMapping("/hello")
    public List<User> selectList(){
    return userServlce.selectList() ;
    }
}

Summary:

  1. The CRUD function of the User table is realized through the above simple steps,
  2. You don't even need to write an XML file
  3. As can be seen from the above steps, integrating mybatis plus is very simple. You only need to introduce the configuration path scanning of the dependent configuration mapper and inherit basemapper < >
  4. MybatisPlus is more powerful than that. If you want to understand its powerful functions in detail, look down slowly

4. Configure log

#Configuration log
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

Summary:

  • After configuring the log, you will fall in love with mybatis plus

5.CRUD extension

1. Insert data

    @Test
    public void show01(){
        User user = new User();
        user.setName("Xingjian good bully");
        user.setAge(18);
        user.setEmail("132456@qq.com");
//        insert data
        mapper.insert(user);
    }

Note: the default value of database insert id is snowflake id

2. Generate policy column from primary key

  • Automatic growth

    advantage:
    1)Simple, convenient code, acceptable performance.
    2)number ID Natural sorting is very helpful for paging or sorting results.
    Disadvantages:
    1)The syntax and implementation of different databases are different. It needs to be handled during database migration or multi database version support.
    2)In the case of single database, read-write separation or one master and multiple slaves, only one master database can be generated. Risk of single point of failure.
    3)When the performance fails to meet the requirements, it is difficult to expand. (not applicable to massive and high concurrency)
    4)If you encounter multiple systems that need to be merged or involve data migration, it will be quite painful.
    5)There will be trouble when dividing tables and libraries.
    6)Not necessarily continuous, similar MySQL,When generating new ID If the transaction is rolled back, subsequent transactions will not use this ID Yes. This is a compromise between performance and continuity. In order to ensure continuity, it must be generated after the transaction ends ID,Then there will be performance problems.
    7)In the distributed database, if the self increasing primary key is adopted, it may bring tail hot spots. Distributed databases are often used range When a large number of new records are added, IO It will concentrate on one partition, resulting in hot data.
    
  • UUID

    advantage:
    1)Simple and convenient code.
    2)generate ID Very good performance, basically no performance problems.
    3)It is the only one in the world. It can deal with data migration, system data consolidation, or database change calmly
     Disadvantages:
    1)Without sorting, the trend cannot be guaranteed to increase.
    2)UUID String storage is often used, and the efficiency of query is relatively low.
    3)The storage space is relatively large. If it is a massive database, the storage capacity needs to be considered.
    4)Large amount of transmitted data
    5)Unreadable.
    
  • Redis generated id

    advantage:
    1)It does not depend on the database, is flexible and convenient, and its performance is better than the database.
    2)number ID Natural sorting is very helpful for paging or sorting results.
    Disadvantages:
    1)If not in the system Redis,New components need to be introduced to increase the complexity of the system.
    2)The workload of coding and configuration is relatively large.
    
  • Twitter's snowflake algorithm (distributed id: snowflake id)

    Snowflake is Twitter's open source distributed ID generation algorithm, and the result is a long ID. Its core idea is to use 41bit as the number of milliseconds, 10bit as the machine ID (five bits are the data center and five bit machine ID), 12bit as the serial number within milliseconds (meaning that each node can generate 4096 IDS per millisecond), and finally there is a symbol bit, which is always 0. For the specific implementation code, see https://github.com/twitter/snowflake . The TPS supported by snowflake algorithm can reach about 4.19 million (2 ^ 22 * 1000).

    advantage:
    1)It does not depend on the database, is flexible and convenient, and its performance is better than the database.
    2)ID It is incremented on a single machine according to time.
    Disadvantages:
    1)It is incremental on a single machine, but due to the distributed environment, the clock on each machine cannot be fully synchronized. In the algorithm, the problem of time callback should be solved
    
    Question.
    
  • Generate unique ID with zookeeper

    zookeeper Mainly through its znode The data version is used to generate the serial number, which can generate 32-bit and 64 bit data version numbers. The client can use this version number as the unique serial number.
    Rarely used zookeeper To generate unique ID. Mainly due to the need to rely on zookeeper,And it is a multi-step call API,If the competition is large, it is necessary to consider using distributed locks. Therefore, the performance is not ideal in the distributed environment with high concurrency.
    

3. Self increment of primary key

1. Modify entity class

@Data
public class User {
//    The primary key in the corresponding database (UUID, auto increment id, redis zookeeper id)
    @TableId(type = IdType.AUTO) //Configure primary key auto increment
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

2. Modify database self increment

3. Test

    @Test
    public void show01(){
        User user = new User();
        user.setName("Xingjian good bully");
        user.setAge(18);
        user.setEmail("132456@qq.com");
//        insert data
        mapper.insert(user);
    }

4. Results

5.IdType source code analysis

public enum IdType {
     
    AUTO(0),//Self increment of database ID  
    NONE(1),//The type is not set with primary key      
    INPUT(2),//User input ID
      		 //This type can be filled by registering the auto fill plug-in  
    
//The following three types are automatically filled only when the inserted object ID is empty.     
    ID_WORKER(3),//The globally unique ID (idWorker) is also the default id type     
    UUID(4),//Globally unique ID (UUID)          
    ID_WORKER_STR(5);//String globally unique ID (string representation of idworker) 

Summary:

  1. Understand the advantages and disadvantages of primary key policy columns
  2. Master the integration of primary key by mybatis plus

4. Update data

1. Test code

  /*
    * Test update
    * */
    @Test
    public void show02(){
        User user = new User();
        user.setId(1403046980736827394L);
        user.setName("I'm a good bully");
//        Note that the updateById parameter is an object
        mapper.updateById(user);
    }

Summary:

  • The update of sql is dynamic, and it will be spliced according to the parameters

5. Auto fill

  • Implementation of meta object processor interface: com baomidou. mybatisplus. core. handlers. MetaObjectHandler
  • The annotation filling field @ TableField(.. fill = FieldFill.INSERT) generator policy can also be configured!

1. Add fields to the database

2. Add entity class

//    When adding fields for automatic filling, be sure to use the DATE under util package
    @TableField(fill = FieldFill.INSERT)
    private Date creatTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
}

3. Write a class to implement com baomidou. mybatisplus. core. handlers. Metaobjecthandler interface

@Slf4j
@Component   //Leave it to the Spring container for management
public class MyMetaObjecHandler implements MetaObjectHandler {
//Insert fill policy column
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert Auto fill started");
       this.setFieldValByName("creatTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);

    }
//Update fill policy column
    @Override
    public void updateFill(MetaObject metaObject) {
         log.info("start update  Auto fill started  ");
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}


4. Test

    /*
    * insert data
    * */
    @Test
    public void show01(){
        User user = new User();
        user.setName("Xingjian good bully");
        user.setAge(18);
        user.setEmail("132456@qq.com");
//        insert data
        mapper.insert(user);
    }

    /*
    * Test update
    * */
    @Test
    public void show02(){
        User user = new User();
        user.setId(1403046980736827394L);
        user.setName("I'm a good bully");
        user.setAge(23);
        user.setEmail("test5@baomidou.com");
//        Note that the updateById parameter is an object
        mapper.updateById(user);
    }

5. Results

  1. Source code analysis of FieldFill
public enum FieldFill {
    /**
     * Do not process by default
     */
    DEFAULT,
    /**
     * Insert fill field
     */
    INSERT,
    /**
     * Update fill field
     */
    UPDATE,
    /**
     * Insert and update populated fields
     */
    INSERT_UPDATE
}

matters needing attention:
1. The filling principle is to directly set the value for the attribute of entity!!!
2. Annotation specifies that the attribute must have a value in the corresponding case. If there is no value, the receipt will be null
3. The policies of the default methods provided by metaobjecthandler are: if the attribute has a value, it will not be overwritten; if the filling value is null, it will not be filled
4. The field must declare a TableField annotation, and the attribute fill selects the corresponding policy. This declaration tells mybatis plus that SQL fields need to be reserved and injected
5. The filling processor MyMetaObjectHandler needs to declare @ Component or @ Bean injection in Spring Boot
6. If you want to use the annotation fieldfill XXX is distinguished by field name and field type. The strictInsertFill or strictUpdateFill methods of the parent class must be used
7. There is no need to distinguish the fillStrategy method that can use the parent class according to any

Summary:

  1. Understand the automatic filling of time

  2. Add annotation @ tablefield in attribute (fill = fieldfill. Insert)

  3. Implement interface com baomidou. mybatisplus. core. handlers. MetaObjectHandler

  4. Rewrite two methods: insertFill(MetaObject metaObject) updateFill(MetaObject metaObject)

6. Logical deletion

1. Add field

2. Add field to entity class

    //Logical deletion
    @TableLogic
    private Integer deleted;

3. Add profile

mybatis-plus:
  global-config:
    db-config:
      logic-not-delete-value: 0   #Logic and delete (1 by default)
      logic-delete-value: 1  # Logical delete (0 by default)

4. Register logical deletion

@Configuration
public class MyLogicDeleteHandler {

//    Register deletion logic
@Bean
public ISqlInjector sqlInjector(){
    
    return new LogicSqlInjector();
}
}

5. Test

    /*
    * Logical deletion
    * */
    @Test
    public void show04(){
        int i = mapper.deleteById(1403046980736827394L);
        System.out.println("i = " + i);
    }

   /*
   * Query by id
   * */
    @Test
    public void show05(){
        User user = mapper.selectById(1403046980736827394L);
        System.out.println(user);
    }


6. Results

Summary:

Logical deletion is a false deletion. Change the deleted field status to the deleted status, and the database still has this data

7. Query operation

   /*
   * Query by id
   * */
    @Test
    public void show05(){
        User user = mapper.selectById(1403046980736827394L);
        System.out.println(user);
    }
    /*
    * Test batch query
    * */
    @Test
    public void show06(){

        List<Long> longs = Arrays.asList(1403046980736827395L, 1403046980736827396L, 1403046980736827393L);

        List<User> users = mapper.selectBatchIds(longs);
       users.forEach(System.out::println);
    }

    /*
    * Query by query criteria
    * */
@Test
    public void show(){
        HashMap<String, Object> map = new HashMap<>();

//        Add condition
        map.put("name","Xiaoguo theory java");
        map.put("age","18");

        List<User> users = mapper.selectByMap(map);

        users.forEach(o-> System.out.println("o = " + o));
    }



8 paging query

1. Register paging plug-in

//    Register paging plug-in

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        return paginationInterceptor;
    }


2. Test

    @Test
    public void show07(){

        Page<User> userPage = new Page<>(2,5);
       mapper.selectPage(userPage,null);
        List<User> records = userPage.getRecords();
        
        records.forEach(o-> System.out.println("o = " + o));

    }


3. Results

9. Optimistic lock

When you want to update a record, you want it not to be updated by others
Optimistic lock implementation method:

  • When the record is fetched, the current version is obtained
  • When updating, bring this version
  • When updating, set version = newVersion where version = oldVersion
  • If the version is incorrect, the update fails

1. Register lock assembly

    
    // Register optimistic lock plug-in
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }


2. Add attribute to entity class

@Version // version annotation of optimistic lock
private Integer version;

3. Test

    // Failed to test optimistic lock! Multithreading
    @Test
    public void testVersionFall(){
        // Thread 1
        User user1 = mapper.selectById(1L);
        user1.setName("fan111");
        user1.setAge(14);

        // Thread 2
        User user2 = mapper.selectById(1L);
        user2.setName("fan222");
        user2.setAge(24);
        mapper.updateById(user2);

        //Spin lock to multiple attempts to submit!
        mapper.updateById(user1); //If there is no optimistic lock, it will override the value of the queue jumping thread
    }




6. Performance analysis plug-in

We usually encounter some slow sql in development

Mybatis plus provides performance plug-ins, which will stop running after this time

1. Injection plug-in

//Performance analysis plug-in
    @Bean
    @Profile({"dev","test"}) //Set dev and test environment on
    public PerformanceInterceptor performanceInterceptor(){
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(1);   //The unit is milliseconds (ms)
        performanceInterceptor.setFormat(true);
        return performanceInterceptor;
    }


2. Prepare configuration file

    #Set up development environment
  profiles:
    active: dev

3. Test

    @Test
    public void show06(){

        List<Long> longs = Arrays.asList(1403046980736827395L, 1403046980736827396L, 1403046980736827393L);

        List<User> users = mapper.selectBatchIds(longs);
       users.forEach(System.out::println);
    }

4. Results

5.sql execution is too long. Please perform optimization

     //get data
    public List<T> getRecords() {
        return this.records;
    }

  //Total records after
    public long getTotal() {
        return this.total;
    }

    public long getSize() {
        return this.size;
    }
    public long getCurrent() {
        return this.current;
    }


7. Conditional constructor

    @Test
    public void show9(){
//    Query users whose mailbox is not empty query users whose age is greater than 18

        QueryWrapper<User> wrapper = new QueryWrapper<>();
//        Add condition
        QueryWrapper<User> ge = wrapper.isNotNull("name").isNotNull("email").ge("age", 18);
        mapper.selectList(ge).forEach(o-> System.out.println("o = " + o));


    }

    /*
    * Query by name
    * */
    @Test
    public void show10(){

        QueryWrapper<User> wrapper = new QueryWrapper<>();

        QueryWrapper<User> ge = wrapper.ge("name", "Xiaoguo theory java");

        List<User> users = mapper.selectList(ge);

        System.out.println("users = " + users);

    }

    /*
    * The inquiry age is between 16 and 30
    * */

    @Test
    public void show11(){

        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
//        Add condition
        userQueryWrapper.between("age",16,30);
        Integer integer = mapper.selectCount(userQueryWrapper);
        System.out.println("=============="+integer);
    }


    /*
    * Fuzzy query
    * */
    @Test
    public void show12(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.likeRight("email","test");
        List<User> users = mapper.selectList(wrapper);
    users.forEach(p-> System.out.println("p = " + p));
    }


8. Code generator

package com.xjggb;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;




public class Test {
    public static void main(String[] args) {
        // You need to build an automatic code generator object
        AutoGenerator mpg = new AutoGenerator();

        // Configuration policy
        // 1. Global configuration
        GlobalConfig gc = new GlobalConfig();

       // String projectPath = System.getProperty("user.dir");
        String projectPath = "D:\\mybatis-plus\\hello-mybatis-plus-02";
        gc.setOutputDir(projectPath+"/src/main/java");
        gc.setAuthor("Xiaoguo theory"); gc.setOpen(false);
        gc.setFileOverride(false);

        // Overwrite
        gc.setServiceName("%sService");

        // I prefix to Service
        gc.setIdType(IdType.ID_WORKER);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setSwagger2(true);
        mpg.setGlobalConfig(gc);

        //2. Set data source
        DataSourceConfig dsc = new DataSourceConfig();
//        dsc.setUrl("jdbc:mysql://localhost:3306/kuang_community? useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
        dsc.setUrl("jdbc:mysql://192.168.93.222:3306/user_day?useSSL=false&useUnicode=true&characterEncoding=utf-8");
        dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);

        //3. Package configuration
        PackageConfig pc = new PackageConfig();
        //Just change the entity class name, package name and database configuration
        pc.setModuleName("blog"); pc.setParent("com.xjggb");
        pc.setEntity("entity"); pc.setMapper("mapper");
        pc.setService("service"); pc.setController("controller");
        mpg.setPackageInfo(pc);

        //4. Policy configuration
        StrategyConfig strategy = new StrategyConfig();
        // Set the table name to map. You can add multiple tables
        strategy.setInclude("user");
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
//        Automatic Lombok
        strategy.setEntityLombokModel(true);


        strategy.setLogicDeleteFieldName("deleted");

        // Auto fill configuration
        TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
        TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(gmtCreate); tableFills.add(gmtModified);
        strategy.setTableFillList(tableFills);

/*        // Optimistic lock
        strategy.setVersionFieldName("version");
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true);*/

        // localhost:8080/hello_id_2
        mpg.setStrategy(strategy);
        mpg.execute(); //implement
    }


    }



9. Mybatis plus XML configuration

mybatis-plus:
  mapper-locations: mapper/*.xml
  global-config:
    db-config:
      # Primary key policy
      id-type: auto
      # table prefix 
      table-prefix: t
      # Whether to use underline interval for table name. Default: Yes
      table-underline: true
  # Add mybatis profile path
  config-location: mybatis-config.xml
  # Configure entity class package address
  type-aliases-package: org.ywb.demo.pojo
  # Hump turn
  configuration:
    map-underscore-to-camel-case: true

Summary:

  1. Simplify development with mybatis plus
  2. Greatly improve the development speed

Topics: Java