MyBatis Plus Quick Start (2021.07.16)


1. Getting Started with MyBatis-Plus

1 Introduction

MyBatis-Plus (MP for short) is an enhancement tool of MyBatis, which only enhances and does not change on the basis of MyBatis, and is born to simplify development and improve efficiency. With simple configuration, CRUD operations can be performed quickly, saving a lot of time. Hot loading, code generation, paging, performance analysis and other functions are all available.

2. Create and initialize the database

2.1 Create the database
mybatis_plus
2.2 Create the User table
The corresponding database Schema script is as follows:

CREATE TABLE USER
(
    id BIGINT(20)NOT NULL COMMENT '主键ID',
    NAME VARCHAR(30)NULL DEFAULT NULL COMMENT '姓名',
    age INT(11)NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50)NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
);

The corresponding database Data script is as follows:

INSERT INTO user (id, name, age, email)VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');

3. Confirm the idea configuration

3.1 Open configuration
insert image description here
insert image description here

3.2 Java Compiler
insert image description here

3.3 Coding of projects and files
insert image description here

3.4 Maven configuration

insert image description here

4. Create a project

4.1 Initialize the project
Use Spring Initializr to quickly initialize a Spring Boot project
Group: com.atguigu
Artifact: mybatis_plus
version: 2.2.1.RELEASE
4.2 Introduce dependencies
Note: Please do not introduce MyBatis again after introducing MyBatis-Plus to avoid problems caused by version differences question.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.atguigu</groupId>
    <artifactId>demomptest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demomptest</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath />
    </parent>


    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.2.2.RELEASE</spring-boot.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1</version>
        </dependency>

        <!--mysql依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--lombok用来简化实体类-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>


</dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.7.RELEASE</version>
                <configuration>
                    <mainClass>com.atguigu.demomptest.DemomptestApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

4.3 Install lombok plugin in idea

5. Write code

5.1 Configuration
Add MySQL database related configuration in the application.properties configuration file:
spring boot 2.0 (built-in jdbc5 driver)

#mysql数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root

Spring boot 2.1 and above (built-in jdbc8 driver)
Note: changes in driver and url

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root

Notice:

1. The url here uses the suffix ?serverTimezone=GMT%2B8, because the 8.0 version of the jdbc driver needs to add this suffix, otherwise the following error will be reported when running the test case: java.sql.SQLException:
The server time zone value 'Öйú±ê× ¼Ê±¼ä' is unrecognized or represents more
2. The driver-class-name here uses com.mysql.cj.jdbc.Driver. It is recommended to use this driver in jdbc 8, otherwise there will be WARN information when running the test case
5.2 Startup class
Add the @MapperScan annotation to the Spring Boot startup class to scan the Mapper folder

package com.atguigu.demomptest;

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

@SpringBootApplication
@MapperScan("com.atguigu.demomptest.mapper")
public class DemomptestApplication {
    
    

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

}

5.3 Add entity
Create package entity Write entity class User.java (Lombok is used here to simplify the code)

package com.atguigu.demomptest.entity;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;

import java.util.Date;

@Data
public class User {
    
    

    //@TableId(type = IdType.ASSIGN_ID)
    private Long id;
    private String name;
    private Integer age;
    private String email;

//    @TableField(fill = FieldFill.INSERT)
//    private Date createTime;  //create_time
//
//    @TableField(fill = FieldFill.INSERT_UPDATE)
//    private Date updateTime; //update_time
//
//
//    @Version
//    @TableField(fill = FieldFill.INSERT)
//    private Integer version;
//
//    @TableLogic
//    @TableField(fill = FieldFill.INSERT)
//    private Integer deleted;

}


View compilation results

5.4 Add mapper
Create package mapper Write Mapper interface: UserMapper.java

package com.atguigu.demomptest.mapper;

import com.atguigu.demomptest.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;

@Repository
public interface UserMapper extends BaseMapper<User> {
    
    
}


5.5 Test
Add a test class for functional testing:

@SpringBootTest
class DemomptestApplicationTests {
    
    

    @Autowired
    private UserMapper userMapper;

    @Test
    public void findAll() {
    
    
        List<User> users = userMapper.selectList(null);
        System.out.println(users);
    }
}

Note:
IDEA reports an error at userMapper because the injected object cannot be found, because the class is dynamically created, but the program can be executed correctly.
In order to avoid error reporting, you can add @Repository annotation on the interface of the dao layer
. Through the above simple steps, we have realized the CRUD function of the User table, and even the XML file does not need to be written!
Look at the console output:

5.6 View sql output log

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

Second, the primary key strategy

1. Insert operation

//添加
@Test
public void testAdd() {
    
    
    User user = new User();
    user.setName("lucy");
    user.setAge(20);
    user.setEmail("[email protected]");
    int insert = userMapper.insert(user);
    System.out.println(insert);
}

Note: The database insert id value defaults to: globally unique id

2. MP primary key strategy

2.1 ASSIGN_ID
The default primary key strategy of MyBatis-Plus is: ASSIGN_ID (using the snowflake algorithm)

@TableId(type = IdType.ASSIGN_ID)
private String id;

Snowflake Algorithm: Distributed ID Generator
Snowflake Algorithm is a distributed primary key generation algorithm announced by Twitter, which can ensure the non-duplication of primary keys in different tables and the ordering of primary keys in the same table.
Core idea:
the total length is 64bit (a long type).
The first is a sign bit, 1bit identification. Since the basic type of long is signed in Java, the highest bit is the sign bit, positive numbers are 0, and negative numbers are 1, so id is generally a positive number, and the highest bit is 0.
41bit time cut (millisecond level), which stores the difference between the time cut (current time cut - start time cut), the result is approximately equal to 69.73 years.
10 bits are used as the ID of the machine (5 bits are the data center, and the machine ID of 5 bits can be deployed on 1024 nodes).
12bit is used as the serial number within milliseconds (meaning that each node can generate 4096 IDs per millisecond).
insert image description here

Advantages: On the whole, they are sorted according to time increment, and ID collisions will not occur in the entire distributed system, and the efficiency is high.

2.2 AUTO auto-increment strategy
It is necessary to set the primary key auto-increment when creating the data table.
Configure @TableId(type = IdType.AUTO) in the entity field

@TableId(type = IdType.AUTO)
private Long id;

To affect the configuration of all entities, you can set the global primary key configuration

#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto

3. Autofill and Optimistic Locking

1. Update operation

Note: The sql generated during update is automatically a dynamic sql: UPDATE user SET age=? WHERE id=?

//修改
@Test
public void testUpdate() {
    
    
    User user = new User();
    user.setId(1340868235401764865L);
    user.setName("lucymary");
    int count = userMapper.updateById(user);
    System.out.println(count);
}

2. Autofill

Requirement description:
Some data is often encountered in projects, which are filled in the same way every time, such as record creation time, update time, etc.
We can use the auto-fill function of MyBatis Plus to complete the assignment of these fields
1.1 Database modification
Add new fields of datetime type create_time and update_time to the User table
1.2 Entity class modification
Add fields to the entity and add auto-fill annotations

@TableField(fill = FieldFill.INSERT)
private Date createTime;  //create_time

@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime; //update_time

1.3 Implement the Meta Object Processor Interface
Note: Don't forget to add the @Component annotation

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    
    

    //mp执行添加操作,这个方法执行
    @Override
    public void insertFill(MetaObject metaObject) {
    
    
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    //mp执行修改操作,这个方法执行
    @Override
    public void updateFill(MetaObject metaObject) {
    
    
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

3. Optimistic lock

3.1 Scenarios
Main applicable scenarios: when you want to update a record, you hope that this record has not been updated by others, that is to say, realize thread-safe data update Optimistic lock implementation
method:
when fetching the record, when obtaining the current version
update, bring this When the version
is updated, set version = newVersion where version = oldVersion
If the version is wrong, the update will fail
Next, we will introduce how to use optimistic locks in the Mybatis-Plus project:

4. Optimistic lock implementation process

4.1 Modify the entity class
and add the @Version annotation

@Version
private Integer version;

4.2 Create a configuration file
Create a package config and create a file MybatisPlusConfig.java
At this point, you can delete the @MapperScan scanning annotation in the main class

@Configuration
@MapperScan("com.atguigu.demomptest.mapper")
public class MpConfig {
    
    
    /**
     * 乐观锁插件
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
    
    
        return new OptimisticLockerInterceptor();
    }
}

4.3 Register Optimistic Lock Plugin
Register Bean in MybatisPlusConfig

/**
* 乐观锁插件
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
    
    
return new OptimisticLockerInterceptor();
}

4.4 Optimistic lock test

//测试乐观锁
@Test
public void testOptimisticLocker(){
    
    
    //查询
    User user = userMapper.selectById(1415874405233410050L);
    //修改
    user.setName("zhangshan");
    
    int i = userMapper.updateById(user);
}

4. Query

1. Query


1.1 The foreach function of dynamic sql is completed through multiple id batch query

//多个id批量查询
@Test
public void testSelect1() {
    
    
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
    System.out.println(users);
}

1.2 Simple conditional query
Encapsulate query conditions through map
Note: the key in the map corresponds to the column name in the database. Such as: database user_id, the entity class is userId, then the key of the map needs to fill in user_id

//简单条件查询
@Test
public void testSelect2() {
    
    
    Map<String, Object> columnMap = new HashMap<>();
    columnMap.put("name","Jack");
    columnMap.put("age",20);
    List<User> users = userMapper.selectByMap(columnMap);
    System.out.println(users);
}

2. Pagination

2.1 Paging plug-in
MyBatis Plus has its own paging plug-in, and the paging function can be realized with simple configuration
2.1.1 Adding a paging plug-in
Add @Bean configuration to the configuration class

@Configuration
public class MybatisPlusConfig {
    
    
    /**
     * 乐观锁插件
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
    
    
        return new OptimisticLockerInterceptor();
    }

    /**
     * 分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
    
    
        return new PaginationInterceptor();
    }

}

2.1.2 Test selectPage pagination
Test: finally obtain relevant data through the page object

//分页查询
@Test
public void testSelectPage() {
    
    
    Page<User> page = new Page(1,3);
    Page<User> userPage = userMapper.selectPage(page, null);
    //返回对象得到分页所有数据
    long pages = userPage.getPages(); //总页数
    long current = userPage.getCurrent(); //当前页
    List<User> records = userPage.getRecords(); //查询数据集合
    long total = userPage.getTotal(); //总记录数
    boolean hasNext = userPage.hasNext();  //下一页
    boolean hasPrevious = userPage.hasPrevious(); //上一页

    System.out.println(pages);
    System.out.println(current);
    System.out.println(records);
    System.out.println(total);
    System.out.println(hasNext);
    System.out.println(hasPrevious);
}

2.2 Test selectMapsPage pagination
When a specific query column is specified, it is hoped that the pagination result list will only return the queried column instead of many null values.
Test selectMapsPage pagination: the result set is a Map

@Test
public void testSelectMapsPage() {
    
    
	//Page不需要泛型
	Page<Map<String, Object>> page = newPage<>(1, 5);
	Page<Map<String, Object>> pageParam = userMapper.selectMapsPage(page, null);
	List<Map<String, Object>> records = pageParam.getRecords();
	records.forEach(System.out::println);
	System.out.println(pageParam.getCurrent());
	System.out.println(pageParam.getPages());
	System.out.println(pageParam.getSize());
	System.out.println(pageParam.getTotal());
	System.out.println(pageParam.hasNext());
	System.out.println(pageParam.hasPrevious());
}

5. Deletion and logical deletion

1. Delete

1.1 Delete records based on id

@Test
public void testDeleteById(){
    
    
    int result = userMapper.deleteById(5L);
system.out.println(result);
}

1.2 Batch delete

@Test
public void testDeleteBatchIds() {
    
    
    int result = userMapper.deleteBatchIds(Arrays.asList(8, 9, 10));
system.out.println(result);
}

1.3 Simple conditional deletion

@Test
public void testDeleteByMap() {
    
    
HashMap<String, Object> map = new HashMap<>();
map.put("name", "Helen");
map.put("age", 18);
    int result = userMapper.deleteByMap(map);
system.out.println(result);
}

2. Tombstone

2.1 Physical deletion and logical deletion
Physical deletion: real deletion, the corresponding data is deleted from the database, and the deleted data cannot be queried later
Logical deletion: false deletion, the status of the field representing whether the corresponding data is deleted is changed to "deleted status", you can still see this data record in the database

Scenarios for logical deletion:
data recovery can be performed,
there is associated data, and it is inconvenient to delete

2.2 Tombstone implementation process
2.2.1 Database modification
Add deleted field

ALTERTABLE `user` ADD COLUMN `deleted` boolean DEFAULT false

2.2.2 Entity class modification
Add deleted field and add @TableLogic annotation

@TableLogic
private Integer deleted;

2.2.3 Configuration (optional)
application.properties Add the following configuration, this is the default value, if your default value is the same as the default value of mp, this configuration is optional

mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

2.2.4 Test
After the test, it was found that the data was not deleted, and the value of the deleted field changed from 0 to 1.
After the test, the printed SQL statement was analyzed and it was an update
Note: before being deleted, the value of the deleted field of the data must be 0 , can be selected to perform logical delete operation

@Test
public void testLogicDelete() {
    
    
    int result = userMapper.deleteById(1L);
system.out.println(result);
}

2.2.5 Test the query after logical deletion
The query operation in MyBatis Plus will also automatically add the judgment of the logical deletion field

@Test
public void testLogicDeleteSelect() {
    
    
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}

6. Conditional constructor wrapper and common interfaces

1. Introduction to wrappers

insert image description here

Wrapper: conditional construction abstract class, the topmost parent class
AbstractWrapper: used for query condition encapsulation, where condition for generating sql
QueryWrapper: query condition encapsulation
UpdateWrapper: update condition encapsulation
AbstractLambdaWrapper: use Lambda syntax
LambdaQueryWrapper: query wrapper for Lambda syntax use
LambdaUpdateWrapper : Lambda update package Wrapper

2. Test cases

2.1 ge、gt、le、lt、isNull、isNotNull

@Test
public void testQuery() {
    
    
    QueryWrapper<User>queryWrapper = new QueryWrapper<>();
    queryWrapper.isNotNull("name").ge("age", 18).isNotNull("email");
    List<User> users = userMapper.selectList(queryWrapper);
    System.out.println(users);
}

2.2 eq, ne
Note: seletOne() returns one entity record, and an error will be reported when there are more than one

@Test
public void testSelectOne() {
    
    
    QueryWrapper<User>queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("name", "Tom");
    User user = userMapper.selectOne(queryWrapper);//只能返回一条记录,多余一条则抛出异常
    System.out.println(user);
}

2.3 between and notBetween
contain size boundaries

@Test
public void testSelectCount() {
    
    
    QueryWrapper<User>queryWrapper = new QueryWrapper<>();
    queryWrapper.between("age", 20, 30);
    Integer count = userMapper.selectCount(queryWrapper); //返回数据数量
    System.out.println(count);
}

2.4 like, notLike, likeLeft, likeRight
selectMaps() returns a list of Map collections, usually used with select()

@Test
public void testSelectMaps() {
    
    
    QueryWrapper<User>queryWrapper = new QueryWrapper<>();
    queryWrapper
            .select("name", "age")
            .like("name", "t")
            .likeRight("email", "t");
    List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表
    maps.forEach(System.out::println);
}

2.5 orderBy、orderByDesc、orderByAsc

@Test
public void testSelectListOrderBy() {
    
    
    QueryWrapper<User>queryWrapper = new QueryWrapper<>();
    //queryWrapper.orderByAsc("age");
    queryWrapper.orderByDesc("age", "id");
    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}

3. Query method

insert image description here
insert image description here

Guess you like

Origin blog.csdn.net/weixin_44531966/article/details/118795446