Mybatis plus - automatic code generator

Posted by blueguitar on Mon, 17 Jan 2022 22:47:27 +0100

πŸ“’πŸ“’πŸ“’πŸ“£πŸ“£πŸ“£

Hello! Hello, everyone. I'm [one heart classmate], a highly motivated [Java domain blogger]! 😜😜😜

✨ Writing style of [one heart students]: I like to explain every knowledge point in [easy to understand] style, rather than using [tall and tall] official statement.

✨ The field of the blog is the learning of back-end technology, and more back-end technology and learning experience will be continuously updated in the future.

✨ If there are [cute] who are interested in [back-end technology], please pay attention to [one heart students] πŸ’žπŸ’žπŸ’ž

❀️❀️❀️ Thank you, big and small! ❀️❀️❀️ ‘

catalogue

preface

1, Introduction

2, Automatic code generator construction

preparation

2.1. Create a SpringBoot project.

2.2} import dependency

2.3 preparation of configuration files

2.4 automatic code generator

2.5 start and run code generator class

2.6 writing auto fill processor

2.7 optimistic lock and logical deletion configuration

2.8 test

3, CRUD in Service

3.1} insertion operation

3.2} insert or update operation

3.3 delete

3.4 update operation

3.5 query operation

3.5.1} single query

3.5.2 batch query

3.5.3 query quantity

Summary

preface

Recall our previous development process. First, we need to write entity classes corresponding to database tables, and then create packages (mapper,service,impl) at various levels. Does this process feel particularly long? Now an artifact has appeared, which is the automatic code generator of mpbatis plus.

1, Introduction

The automatic code generator is very easy to use. We only need to provide the table name of our database, and then let the generator automatically help us complete the creation of various codes. The whole process is very refreshing, which can be said to be the welfare of overtime workers!

Now let's explain how to build this automatic code generator!

2, Automatic code generator construction

preparation

CREATE DATABASE mybatis_plus_db;

USE `mybatis_plus_db`;

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'User primary key',
  `name` varchar(20) DEFAULT NULL COMMENT 'User name',
  `age` int DEFAULT NULL COMMENT 'User age',
  `version` int DEFAULT '1' COMMENT 'Optimistic lock',
  `deleted` int DEFAULT '0' COMMENT 'Logical deletion',
  `create_time` datetime DEFAULT NULL COMMENT 'Creation time',
  `update_time` datetime DEFAULT NULL COMMENT 'Update time',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1482996505408204804 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

The database structure is as follows:

2.1. Create a SpringBoot project.

Select web dependency.

2.2} import dependency

        <!-- Database driven -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

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

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

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

        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.2</version>
        </dependency>

2.3 preparation of configuration files

application.properties:

# 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
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

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

# Configure logical deletion
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

2.4 automatic code generator

package com.yixin;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
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 org.junit.platform.commons.util.StringUtils;

import java.util.ArrayList;
import java.util.Scanner;

public class CodeGenerator {


    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("Please enter" + tip + ": ");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotBlank(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("Please enter the correct" + tip + "!");
    }





    public static void main(String[] args) {
        // Code generator 
        AutoGenerator mpg = new AutoGenerator();

        // Global configuration
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");//Set code generation path
        gc.setFileOverride(true);//Overwrite previous file
        gc.setOpen(false);//Open build directory
        gc.setAuthor("yixin");//Set project author name
        gc.setIdType(IdType.AUTO);//Set primary key policy
        gc.setBaseResultMap(true);//Generate basic ResultMap
        gc.setBaseColumnList(true);//Generate basic ColumnList
        gc.setServiceName("%sService");//Remove service default prefix
        gc.setDateType(DateType.ONLY_DATE);//Set time type
        mpg.setGlobalConfig(gc);

        // Data source configuration
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("123456");
        mpg.setDataSource(dsc);

        // Package configuration
        PackageConfig pc = new PackageConfig();
        pc.setParent("com.yixin");
        pc.setMapper("mapper");
        pc.setXml("mapper.xml");
        pc.setEntity("pojo");
        pc.setService("service");
        pc.setServiceImpl("service.impl");
        pc.setController("controller");
        mpg.setPackageInfo(pc);

        // Policy configuration
        StrategyConfig sc = new StrategyConfig();
        sc.setNaming(NamingStrategy.underline_to_camel);
        sc.setColumnNaming(NamingStrategy.underline_to_camel);
        sc.setEntityLombokModel(true);//Automatic lombok
        sc.setRestControllerStyle(true);
        sc.setControllerMappingHyphenStyle(true);

        sc.setLogicDeleteFieldName("deleted");//Set logical deletion

        //Set auto fill configuration
        TableFill gmt_create = new TableFill("create_time", FieldFill.INSERT);
        TableFill gmt_modified = new TableFill("update_time", FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFills=new ArrayList<>();
        tableFills.add(gmt_create);
        tableFills.add(gmt_modified);
        sc.setTableFillList(tableFills);

        //Optimistic lock
        sc.setVersionFieldName("version");
        sc.setRestControllerStyle(true);//Hump naming



      //  sc.setTablePrefix("tbl_");  Set table name prefix
        sc.setInclude(scanner("Table name, separated by multiple English commas").split(","));
        mpg.setStrategy(sc);

        // Generate code
        mpg.execute();
    }

}

2.5 start and run code generator class

Enter our table name in the console: user

Then it's done!

See the effect:

For all packages under java, we didn't write them ourselves, but the code generator automatically built them for us!

2.6 writing auto fill processor

On the basis of the code generator, we just need to write the automatically populated processor class as before.

package com.yixin.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

@Slf4j
@Component // Don't forget to add the processor to the IOC container!
public class MyMetaObjectHandler implements MetaObjectHandler {
    // Population policy at insertion
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill.....");
        // setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    // Population policy when updating
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill.....");
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

2.7 optimistic lock and logical deletion configuration

package com.yixin.config;

import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

// Scan our mapper folder
@MapperScan("com.yixin.mapper")
@EnableTransactionManagement
@Configuration // Configuration class
public class MyBatisPlusConfig {

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

    // Delete components logically!
    @Bean
    public ISqlInjector sqlInjector() {
        return new LogicSqlInjector();
    }

}

That's it! Let's write a test class to test it.

2.8 test

(1) Test add data

package com.yixin;

import com.yixin.pojo.User;
import com.yixin.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class AutoApplicationTests {

    @Autowired
    private UserService userService;

    @Test
    void test1() {

        User user=new User();
        user.setName("yixin");
        user.setAge(18);

        boolean flag=userService.save(user);
        System.out.println(flag);
    }
}

Output:

It can be found that a piece of data was successfully inserted.

(2) Test the controller layer to get data

package com.yixin.controller;


import com.yixin.pojo.User;
import com.yixin.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * <p>
 *  Front end controller
 * </p>
 *
 * @author yixin
 * @since 2022-01-17
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @ResponseBody
    @RequestMapping("/all")
    public List<User> get(){

        return  userService.list(null);
    }

}

Start main startup class:

package com.yixin;

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

@SpringBootApplication
@MapperScan("com.yixin.mapper")
public class AutoApplication {

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

}

Enter in the browser: http://localhost:8080/user/all

We have successfully obtained our data.

3, CRUD in Service

3.1} insertion operation

SaveΒ 

// Insert a record (select field, policy insert)
boolean save(T entity);
// Insert (batch)
boolean saveBatch(Collection<T> entityList);

Parameter description

typeParameter namedescribe
TentityEntity object
Collection<T>entityListEntity object collection

use

(1) Insert a piece of data

    @Test
    void contextLoads() {

        User user=new User();
        user.setName("yixin");
        user.setAge(18);

        boolean flag=userService.save(user);
        System.out.println(flag);
    }

(2) Batch insert data

    @Test
    void test3() {

        List<User> userList=new ArrayList<>();

        User user=new User();
        user.setName("zhangsan");
        user.setAge(26);

        User user2=new User();
        user2.setName("lisi");
        user2.setAge(27);

        userList.add(user);
        userList.add(user2);

        boolean flag=userService.saveBatch(userList);
        System.out.println(flag);
    }

3.2} insert or update operation

SaveOrUpdate

// Update record exists in TableId annotation. Insert a record
boolean saveOrUpdate(T entity);
// If the updateWrapper attempts to update, do you want to continue with the saveOrUpdate(T) method
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// Batch modify insert
boolean saveOrUpdateBatch(Collection<T> entityList);

Parameter description

typeParameter namedescribe
TentityEntity object
Wrapper<T>updateWrapperEntity object encapsulation operation class UpdateWrapper
Collection<T>entityListEntity object collection

use

Requirement: insert a piece of data. If the data exists in the database, update it. If it does not exist, insert it.

    @Test
    void test5() {

        User user=new User();
        user.setName("wangwu");
        user.setAge(18);

        boolean flag=userService.saveOrUpdate(user);
        System.out.println(flag);

    }

3.3 delete

Remove

// Delete the record according to the entity condition
boolean remove(Wrapper<T> queryWrapper);
// Delete by ID
boolean removeById(Serializable id);
// Delete the record according to the columnMap condition
boolean removeByMap(Map<String, Object> columnMap);
// Delete (batch delete according to ID)
boolean removeByIds(Collection<? extends Serializable> idList);

Parameter description

typeParameter namedescribe
Wrapper<T>queryWrapperEntity wrapper class QueryWrapper
SerializableidPrimary key ID
Map<String, Object>columnMapTable field map object
Collection<? extends Serializable>idListList of primary key ID S

use

Requirement: delete all user information with name "lisi".

    @Test
    void test6() {

        QueryWrapper<User> wrapper=new QueryWrapper<>();
        wrapper.like("name","lisi");
        
        boolean flag=userService.remove(wrapper);
        System.out.println(flag);

    }

3.4 update operation

UpdateΒ 

// According to the UpdateWrapper condition, sqlset needs to be set for updating records
boolean update(Wrapper<T> updateWrapper);
// Update the record according to the whereWrapper condition
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// Select modify according to ID
boolean updateById(T entity);
// Batch update by ID
boolean updateBatchById(Collection<T> entityList);

Parameter description

typeParameter namedescribe
Wrapper<T>updateWrapperEntity object encapsulation operation class UpdateWrapper
TentityEntity object
Collection<T>entityListEntity object collection

use

Requirement: change the user whose user name is "yixin" to "one student".

    @Test
    void test7() {

        QueryWrapper<User> wrapper=new QueryWrapper<>();
        wrapper.eq("name","yixin");

        User user =userService.getOne(wrapper);
        user.setName("One heart classmate");

        boolean flag=userService.updateById(user);
        System.out.println(flag);
    }

3.5 query operation

3.5.1} single query

Get

// Query by ID
T getById(Serializable id);
// Query a record according to the Wrapper. If there are more than one result set, exceptions will be thrown. Take one randomly and add the limiting condition Wrapper last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// Query a record according to the Wrapper
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// Query a record according to the Wrapper
Map<String, Object> getMap(Wrapper<T> queryWrapper);

Parameter description

typeParameter namedescribe
SerializableidPrimary key ID
Wrapper<T>queryWrapperThe entity object encapsulates the operation class QueryWrapper
booleanthrowExIf there are multiple result s, do you throw an exception
TentityEntity object

use

Requirements: query a user whose name is "one heart". Remember, only one user.

    @Test
    void test8() {

        QueryWrapper<User> wrapper=new QueryWrapper<>();
        wrapper.like("name","Wholeheartedly").last("LiMIT 1");

        User user=userService.getOne(wrapper);
        System.out.println(user);
    }

3.5.2 batch query

ListΒ 

// Query all
List<T> list();
// Query list
List<T> list(Wrapper<T> queryWrapper);
// Query (batch query by ID)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// Query (based on columnMap criteria)
Collection<T> listByMap(Map<String, Object> columnMap);
// Query all lists
List<Map<String, Object>> listMaps();
// Query list
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// Query all records
List<Object> listObjs();
// Query all records according to Wrapper conditions
List<Object> listObjs(Wrapper<T> queryWrapper);

Parameter description

typeParameter namedescribe
Wrapper<T>queryWrapperThe entity object encapsulates the operation class QueryWrapper
Collection<? extends Serializable>idListList of primary key ID S
Map<?String, Object>columnMapTable field map object

use

Requirement: query all user information with name "one heart"

    @Test
    void test9() {

        QueryWrapper<User> wrapper=new QueryWrapper<>();
        wrapper.like("name","Wholeheartedly");
        
        List<User> userList=userService.list(wrapper);
        System.out.println(userList);
    }

3.5.3 query quantity

CountΒ 

// Total records queried
int count();
// Query the total number of records according to Wrapper conditions
int count(Wrapper<T> queryWrapper);

Parameter description

typeParameter namedescribe
Wrapper<T>queryWrapperThe entity object encapsulates the operation class QueryWrapper

use

Demand: query the number of users aged 18.

    @Test
    void test10() {

        QueryWrapper<User> wrapper=new QueryWrapper<>();
        wrapper.eq("age",18);

        int count=userService.count(wrapper);

        System.out.println(count);
    }

Summary

The above is how to build an automatic code generator and CRUD operation in the Service layer sorted out by [one student]. I believe you can feel the [high efficiency] of mybatis plus more and more. It can really save us a lot of effort in our development!

If this [article] is helpful to you, I hope I can praise [one heart classmate] πŸ‘οΌŒ It's not easy to create. Compared with the official statement, I prefer to explain every knowledge point in [easy to understand] style. If there are cute kids who are interested in [back-end technology], they are also welcome to pay attention ❀ ️ ❀ ️ ❀ [one student] ❀ ️ ❀ ️ ❀ Finally, I will bring you great [harvest and surprise] πŸ’•πŸ’•!

Topics: Java Spring Boot mybatis-plus intellij-idea