MyBatisPlus official + mad God

Posted by drorshem on Thu, 20 Jan 2022 16:38:21 +0100

MyBatisPlus overview

Required Foundation: MyBatis, Spring, Spring MVC

Why learn it? MyBatisPlus can save us a lot of working time, and all CRUD codes can be completed automatically!

JPA,tk-mapper,MyBatisPlus

Lazy!

brief introduction

What is it? MyBatis is meant to simplify JDBC operations!

Official website: Introduction | mybatis plus (Baidu. Com) , simplify Mybaits!

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, and there is a powerful condition constructor to meet various use requirements
  • Support Lambda formal call: it is convenient to write various query conditions through Lambda expression, and there is no need to worry 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

Support database

Any database that can crud using mybatis and supports standard sql

Frame structure

[the external chain picture transfer fails, and the source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-lMZkyekV-1625980277476)(MyBatisPlus notes crazy God said Java. Assets / mybatis plus framework. JPG)]

Code hosting

Gitee (opens new window)| Github

Quick start

Using third-party components:

1. Import corresponding dependencies

2. Study how dependencies are configured

3. How to write the code

4. Improve and expand technical capability!

Steps:

  1. Create database mybatis_plus

  2. Create user table

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)
);
--In real development, version(Le Guansuo) delete(Logical deletion) gmt_create,gmt_modified

The corresponding database Data script is as follows:

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');
  1. Initialization project

Create an empty Spring Boot project

have access to Spring Initializer (opens new window) Quickly initialize a Spring Boot project

  1. Add dependency
    <!-- Database driven -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <!-- lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.3</version>
    </dependency>

Note: we can save a lot of code by using mybatis plus. Try not to import mybatis and mybatis plus at the same time! Version difference!

  1. Configuration database

In application Add MySQL database configuration in the YML configuration file:

# mysql 5 drives different com mysql. jdbc. Driver
# mysql 8 drives different com mysql. cj. jdbc. Driver, need to add time zone configuration serverTimezone=GMT%2B8

# DataSource Config
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8

Add the @ MapperScan annotation in the Spring Boot startup class and scan the Mapper folder:

@SpringBootApplication
@MapperScan("com.mingm.mapper")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(QuickStartApplication.class, args);
    }

}
  1. code

Write entity class user Java (used here) Lombok (opens new window) Simplified code)

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

Write Mapper class usermapper java

//Inherit the basic interface BaseMapper on the corresponding mapper
@ResponseBody //Represents the persistence layer
public interface UserMapper extends BaseMapper<User> {
    //All CRUD operations have been built in
    //You don't need a lot of configuration files like before
}
  1. Start using

Add a test class for function test:

@SpringBootTest
public class SampleTest {

    // It inherits BaseMapper, and all methods use their own parent class
    // We can also write our own extension methods!
    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSelect() {
        System.out.println(("----- selectAll method test ------"));
        // The parameter is a Wrapper and a condition constructor. We don't need to use null here
        // Query all users
        List<User> userList = userMapper.selectList(null);
        Assert.assertEquals(5, userList.size());
        userList.forEach(System.out::println);
    }

}

The parameter of the selectList() method in UserMapper is the MP built-in conditional Wrapper, so it is unconditional if it is not filled in

Console output:

User(id=1, name=Jone, age=18, email=test1@baomidou.com)User(id=2, name=Jack, age=20, email=test2@baomidou.com)User(id=3, name=Tom, age=28, email=test3@baomidou.com)User(id=4, name=Sandy, age=21, email=test4@baomidou.com)User(id=5, name=Billie, age=24, email=test5@baomidou.com)

TIP

For a complete code example, please move to: Spring Boot quick start example (opens new window)| Spring MVC quick start example (opens new window)

Thinking?

1. Who wrote SQL for us? Mybatis plus is all written!

2. Where did the method come from? Mybatis plus is all written!

Configuration log

All our sql is invisible now. We want to know how it is executed, so we must look at the log

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

After configuring the log, you need to pay attention to the automatically generated SQL in later learning, and you will like mybatis plus!

Crud & Extension

Insert operation

Insert insert

@Testpublic void testInsert() {    User user = new User();    user.setName("Dainel");    user.setAge(3);    user.setEmail("daniel@alibaba.com");    int result = userMapper.insert(user);// Help us automatically generate system id out. println(result);//  Number of rows affected system out. println(user);//  Discovery: id auto backfill}

The default value of the database insert id is the global unique id

Primary key generation strategy

Default ID_WORKER globally unique id

Generation of unique id of distributed system: https://www.cnblogs.com/haoxinyue/p/5208136.html

Snowflake algorithm:

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 (5 bits are the data center and 5 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. Can guarantee almost the only one in the world!

Primary key auto increment

We need to configure primary key auto increment:

  1. @ TableId(type = IdType.AUTO) on entity class field
  2. The database fields must be self incremented

  1. Just test again

The remaining IdType source code is explained

public enum IdType {    AUTO(0), // Add NONE(1) to the database id. / / the primary key INPUT(2) is not set. / / enter it manually and write the id yourself_ Worker (3), / / default globally unique id UUID (4), / / globally unique id UUID id_ WORKER_ STR(5); //  id_ Worker string notation}

update operation

//Test update @Testpublic void testUpdate () {User user = new User (); / / automatically splice SQL SQL user.setId (6L) by condition; user.setName ("pay attention to my WeChat official account"); (18); / / Note: but parameter is an object = = = (()); (()); (});}

All sql is automatically configured for you dynamically!

Auto fill

Creation time and modification time! These operations are generally completed automatically. We don't want to update them manually!

**Alibaba Development Manual: * * all database tables: gmt_create,gmt_modified almost all tables should be configured! And need automation!

Method 1: database level (database modification is not allowed during work)

  1. Add a new field create in the table_ time,update_ time

  2. To test the insertion method again, we need to synchronize the entity class first!

private LocalDateTime createTime;private LocalDateTime updateTime;

Just update the view results again.

Method 2: code level

  1. Delete the default value and update the database!

  1. Annotation needs to be added to the field attribute of the entity class
public class User {       ....            // be careful! Here, it needs to be marked as the filling field @ tablefield (fill = fieldfill. Insert) private date createtime@ TableField(fill = FieldFill.INSERT_UPDATE)    private Date updateTime;}
  1. Write a processor to process this annotation! Custom implementation class MyMetaObjectHandler
@Slf4j@Component // Don't forget to add the processor to the IOC container. public class MyMetaObjectHandler implements MetaObjectHandler {/ / filling policy during insertion @ override public void insertfill (metaobject metaobject) {log.info ("start insert fill..."); this. strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());         this. strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); //  Starting version 3.3.0 (recommended) / / or / / this strictInsertFill(metaObject, "createTime", () -> LocalDateTime. now(), LocalDateTime. class); //  Starting version 3.3.3 (recommended) / / or / / this fillStrategy(metaObject, "createTime", LocalDateTime.now()); //  You can also use (3.3.0 this method has a bug)} / / the filling policy during update @ override public void updatefill (metaobject metaobject) {log.info ("start update fill..."); this. strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); //  Starting version 3.3.0 (recommended) / / or / / this strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime. now(), LocalDateTime. class); //  Starting version 3.3.3 (recommended) / / or / / this fillStrategy(metaObject, "updateTime", LocalDateTime.now()); //  You can also use (3.3.0 has a bug)}}
  1. Test insertion

  2. Test update, observation time

Source FieldFill

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

matters needing attention:

  • The filling principle is to directly set the value for the attribute of entity!!!
  • Annotation specifies that the attribute must have a value in the corresponding case. If there is no value, the receipt will be null
  • The policies of the default methods provided by MetaObjectHandler are: if the property has a value, it will not be overwritten; if the filling value is null, it will not be filled
  • 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
  • The population processor MyMetaObjectHandler needs to declare @ Component or @ Bean injection in Spring Boot
  • 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
  • There is no need to distinguish the fillStrategy method that can use the parent class according to any

Optimistic lock

During the interview, we are often asked about optimistic lock and pessimistic lock.

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

Pessimistic lock: as the name suggests, it always thinks that there is always a problem and locks everything! Do it again!

Implementation of OptimisticLockerInnerInterceptor for optimistic lock:

  • When fetching records, get the current version
  • When updating, bring this version
  • When updating, set version = newVersion where version = oldVersion
  • If the version is not correct, the update fails. Optisticlockerinnerinterceptor
Optimistic lock: 1. Query first to obtain the version number version = 1-- Aupdate user set name = "MINGM", version = version + 1where id = 2 and version = 1-- B The thread finishes first. At this time version = 2,Will cause A Modification failed! update user set name = "MINGM", version = version + 1where id = 2 and version = 1

Steps:

  1. Add a version field to the database

  1. Add the @ Version annotation to the field of the entity class
@Version // Version annotation of optimistic lock private Integer version;

explain:

  • The only supported data types are: int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • newVersion = oldVersion + 1 under integer type
  • newVersion will be written back to entity
  • Only updateById(id) and update(entity, wrapper) methods are supported
  • Under the update(entity, wrapper) method, the wrapper cannot be reused!!!
  1. Register components and write Config files!
// Spring Boot mode@ Configuration@MapperScan("modify as needed") public class MybatisPlusConfig {/ * * * old version * / @ bean public optisticlockerinterceptor optisticlockerinceptor() {return new optisticlockerinceptor();} / * ** New version * / @ bean public mybatisplusinterceptor mybatisplusinterceptor() {mybatisplusinterceptor mybatisplusinterceptor = new mybatisplusinterceptor(); mybatisplusinterceptor.addinnerinterceptor (New optimizationlockerinnerinterceptor()); / / optimistic lock plug-in return mybatisPlusInterceptor;}}
  1. Test it and check the test results.
    // Successfully test optimistic lock @ test public void testversionsuccess() {/ / 1. Query user information user user user = usermapper.selectbyid (1L); / / 2. Modify user information user.setname ("fan"); user.setage (24); / / 3. Update userMapper.updateById(user);}// Test lock update failed! @ test public void testversionfall() {/ / thread 1 user user1 = usermapper.selectbyid (1L); user1.setname ("fan111"); user1.setage (14); / / thread 2 simulates another thread to perform queue jumping operation, user user2 = usermapper.selectbyid (1L); user2.setname ("fan222"); user2.setage (24) ;         userMapper. updateById(user2);                // Spin lock to multiple attempts to submit! userMapper.updateById(user1); // If there is no optimistic lock, it will overwrite the value of the queue jumping thread}

Paging query

Pagination is used as much as ten times in the website!

  1. The original uses limit for paging

  2. pageHelper third party plug-in

  3. MybatisPlus has a built-in paging plug-in

How to use?

  1. Add a paging plug-in to the configuration file
    // Latest version @ bean public mybatisplusinterceptor mybatisplusinterceptor() {mybatisplusinterceptor interceptor = new mybatisplusinterceptor(); mybatisplusinterceptor.addinnerinterceptor (New optimizationlockerinnerinterceptor()); / / optimistic lock plug-in interceptor.addinnerinterceptor (New paginationinnerinnerinterceptor (dbtype. MySQL) );// Paging plugin return interceptor;}
  1. UserMapper.xml is equivalent to writing a common list query, and mybatis plus automatically pages for you
<mapper namespace="com.mingm.mapper.UserMapper">    <select id="selectPageVo" resultType="com.mingm.pojo.User">        SELECT * FROM user WHERE age=#{age}    </select></mapper>
  1. Directly use the Page object to call paging!
    @Test    public void testPage(){        // Parameter 1: current page. / / parameter 2: page size. / / after using the paging plug-in, all paging operations become simple! Page<User> page = new Page<>(2,5);         userMapper. selectPage(page,null);         page. getRecords(). forEach(System.out::println);         System. out. println(page.getTotal());    }    @ Test public void selectuserpage() {/ / do not perform count sql optimization to solve the problem that MP cannot automatically optimize SQL. At this time, you need to query the count part yourself. / / page.setOptimizeCountSql(false); / / when total is less than 0 or set setSearchCount(false) The paging plug-in will not perform count query. / / key points!! The object returned by paging and the object passed in are the same page < user > userpage = new page < > (1,2); userMapper. selectPageVo(userPage,11);// Here 11 are the custom parameters in xml! userPage.getRecords().forEach(System.out::println);        System.out.println(userPage.getTotal());    }

Delete operation

// Test delete @ testpublic void testdelete() {usermapper. Deletebyid (6L);}// Test batch delete @ testpublic void testdeletebatchid() {usermapper.deletebatchids (arrays. Aslist (1287326823914405893l, 1287326823914405894l));}// Delete @ testpublic void testdeletebymap() {HashMap < string, Object > map = new HashMap < > (); map.put ("name", "mingm"); usermapper.deletebymap (map);}

We will encounter some problems in our work: logical deletion!

Logical deletion

Physical delete: remove directly from the database

Logical deletion: it is not removed from the database, but made effective through a variable! deleted=0 --> deleted=1

Administrators can view deleted records! Prevent data loss! Similar to recycle bin!

Field type support Description:

  • All data types are supported (integer, Boolean, localdatetime are recommended)
  • If the database field uses datetime, the logical undeleted value and deleted value can be configured as string null, and the other value can be configured as a function to obtain the value, such as now()

Appendix:

  • Logical deletion is a scheme to facilitate data recovery and protect the value of data itself, but it is actually deletion.
  • If you need to check it frequently, you should not use logical deletion, but represent it in a state.

Test:

  1. Add a deleted field in the database table

  2. Add @ TableLogic annotation to the entity class field

@TableLogic // private Integer deleted;
  1. Configure com baomidou. mybatisplus. core. config. GlobalConfig$DbConfig
  • application.yml
mybatis-plus:  configuration:    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  mapper-locations: mybatis-plus/*.xml  global-config:    db-config:#      logic-delete-field: deleted  # Global logically deleted entity field name(since 3.3.0,Step 2 can be ignored after configuration)      logic-delete-value: 1 # Logical deleted value(The default is 1)      logic-not-delete-value: 0 # Logical undeleted value (default is 0)
  1. Just test!

The record is still in the database, but the value has changed!

Conditional constructor

Very important: wrapper

We can use it instead of writing some complex sql!

Test!

package com.mingm.springbootmybatisplus;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mingm.mapper.UserMapper;
import com.mingm.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.ArrayList;
import java.util.List;
import java.util.Map;

@SpringBootTest
public class WrapperTests {
    @Autowired
    private UserMapper userMapper;

    @Test
    void test1(){
        //Query the user whose name is not empty and whose mailbox is not empty. The user's age is greater than or equal to 12
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.isNotNull("name")
                .isNotNull("email")  //email field is not empty
                .ge("age",12);  //Greater than or equal to >=
        userMapper.selectList(wrapper).forEach(System.out::println);
    }

    @Test
    void test2(){
        //Query name Jack
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("name", "Jack");
        //SELECT id,name,age,email,version,create_time,update_time,deleted FROM user WHERE deleted=0 AND (name = ?)
        User user = userMapper.selectOne(wrapper);
        System.out.println(user);
    }
    @Test
    void test3(){
        //Query the number of users aged between 19 and 21, including!
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("age", 20, 21); //section
        //SELECT COUNT( * ) FROM user WHERE deleted=0 AND (age BETWEEN ? AND ?)
//        Integer count = userMapper.selectCount(wrapper);
        ArrayList<User> userList = (ArrayList<User>) userMapper.selectList(wrapper);
        //SELECT id,name,age,email,version,create_time,update_time,deleted FROM user WHERE deleted=0 AND (age BETWEEN ? AND ?)
        userList.forEach(System.out::println);
        System.out.println(userList.size());
    }

    //Fuzzy query
    @Test
    void test4(){
        //Query users aged between 19 and 30
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //left and right
        wrapper.notLike("name", "A")
                .likeRight("email", "t");
//        Preparing: SELECT id,name,age,email,version,create_time,update_time,deleted FROM user
//        //         WHERE deleted=0 AND (name NOT LIKE ? AND email LIKE ?)
//        ==> Parameters: %b%(String), t%(String)
        List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
        maps.forEach(System.out::println);
    }

    @Test
    void test5(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //id is found in the sub query
        wrapper.inSql("id", "select id from user where id < 3");
        List<Object> objects = userMapper.selectObjs(wrapper);
        objects.forEach(System.out::println);
    }

    @Test
    void test6(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //Sort by id
        wrapper.orderByDesc("id");
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

    @Test
    void test7(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //id is found in the sub query
        wrapper.inSql("id", "select id from user where id < 5");
        //SELECT id,name,age,email,version,create_time,update_time,deleted FROM user
        // //     WHERE deleted=0 AND (id IN (select id from user where id < 5))
        List<Object> objects = userMapper.selectObjs(wrapper);
        objects.forEach(System.out::println);
    }
    @Test
    void test8(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //Sort by id
        wrapper.orderByDesc("id");
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }

}

The rest of the test, you can go down and practice more!

Automatic code generator

Code generator | mybatis plus (Baidu. Com)

AutoGenerator is the code generator of mybatis plus. Through AutoGenerator, you can quickly generate the code of Entity, Mapper, Mapper XML, Service, Controller and other modules, which greatly improves the development efficiency.

  • Presentation rendering:

  • Crazy version configuration
public class Code {
    public static void main(String[] args) {
        //You need to build an automatic code generator object
        // Code generator 
        AutoGenerator mpg = new AutoGenerator();
        //Configuration policy

        //1. Global configuration
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("ChanV");
        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/mybatis-plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);

        //3. Package configuration
        PackageConfig pc = new PackageConfig();
        pc.setModuleName("blog");
        pc.setParent("com.chanv");
        pc.setEntity("pojo");
        pc.setMapper("mapper");
        pc.setService("service");
        pc.setController("controller");
        mpg.setPackageInfo(pc);

        //4. Policy configuration
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude("user");    //Set the table name to map
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);    //Automatic lombok
        strategy.setLogicDeleteFieldName("deleted");
        //Auto fill configuration
        TableFill createTime = new TableFill("create_time", FieldFill.INSERT);
        TableFill updateTime = new TableFill("update_time", FieldFill.UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(createTime);
        tableFills.add(updateTime);
        strategy.setTableFillList(tableFills);
        //Optimistic lock
        strategy.setVersionFieldName("version");
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true);     //localhost:8080/hello_id_2
        mpg.setStrategy(strategy);

        mpg.execute();  //Execute code constructor
    }
}

Topics: Java Mybatis mybatis-plus