MyBatisPlus Learning notes

One 、 Quick start

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

 Insert picture description here

Use third-party components :

  1. Import the corresponding dependency
  2. Study how dependencies are configured
  3. How to write code
  4. Improve the ability to expand technology

step

1、 Create database mybatis_plus

2、 establish user surface , Import 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));--  In real development ,version( Optimism lock )、deleted( Logical deletion )、gmt_create、gmt_modifiedDELETE 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');

3、 establish SpringBoot project , Check web rely on

4、 Import dependence

<!-- Database driven --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version></dependency><!--mybatis-plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</version></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>

explain : We use mybatis-plus Can save us a lot of code , Try not to import at the same time mybatis and mybatis-plus!

5、 Connect to database , This step and mybatis identical

# mysql
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

6、 The traditional way :pojo-mapper( Connect mybatis, To configure mapper.xml file )- service - controller

7、 Used mybatis-plus after

  • pojo

    @Data@AllArgsConstructor@NoArgsConstructorpublic class User {private Long id;private String name;private Integer age;private String email;}
  • mapper Interface

    //  In the corresponding Mapper The above inherits the basic interface  BaseMapper@Repository //  Represents the persistence layer public interface UserMapper extends BaseMapper<User> {//  be-all CRUD The operation has been basically completed //  You don't need to configure a lot of files like before }
  • Be careful : We need to scan our mapper All interfaces under the package

     Insert picture description here

  • Test in test class

    @SpringBootTestclass MybatisPlusApplicationTests {//  Inherited BaseMapper, All methods come from the parent class //  We can also write our own extension methods @AutowiredUserMapper userMapper;@Testvoid contextLoads() {//  The parameter is one  Wrapper ,  Conditional constructor , Here we don't have to  null//  Query all users List<User> users = userMapper.selectList(null);users.forEach(System.out::println);}}
  • test result

     Insert picture description here

Think about the problem :

1、SQL Who wrote it for us ?MyBatis-Plus It's all written

2、 Where did the method come from ?MyBatis-Plus It's all written

Two 、 Configuration log

All of us sql Now it's invisible , We want to know how it works , So we have to look at the log !

#  Configuration log  ( System native , Console output )
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

 Insert picture description here

After configuring the log , Later, we need to pay attention to this automatic generation SQL, We'll love MyBatis-Plus !

3、 ... and 、CRUD

1. The insert

Insert Insert

@Testpublic void testInsert() {User user = new User();user.setName("Zhy");user.setAge(3);user.setEmail("zhy@163.com");int result = userMapper.insert(user);//  Help us automatically generate idSystem.out.println(result);//  Rows affected System.out.println(user);//  Find out : id Automatic backfill }

 Insert picture description here

Database insert id The default value is : The only one in the world id

2. Primary key generation policy

Default ID_WORKER Globally unique id

Distributed systems are unique id Generate :https://www.cnblogs.com/haoxinyue/p/5208136.html

Snowflake algorithm :

snowflake yes Twitter Open source distributed ID generating algorithm , The result is a long Type ID. The central idea is this : Use 41bit As milliseconds ,10bit As a machine ID(5 individual bit It's the data center ,5 individual bit Machine ID),12bit As a serial number in milliseconds ( It means that every node can produce 4096 individual ID), And finally, there's a sign bit , Forever 0. Can guarantee almost the only one in the world !

The primary key increases automatically

We need to configure primary key auto increment :

  1. On the entity class field @TableId(type = IdType.AUTO)

  2. Database fields must be self incrementing

     Insert picture description here

  3. Test again

The rest of the source code explanation

public enum IdType {AUTO(0), //  database id Self increasing NONE(1), //  No primary key set INPUT(2), //  Manual input , Write it yourself id// The following three are not officially recommended ID_WORKER(3), //  Default global unique idUUID(4), //  Globally unique id uuidID_WORKER_STR(5); // ID_WORKER  String representation }

3. update operation

// Test update @Testpublic void testUpdate(){User user = new User();//  Automatically stitching dynamic through conditions sqluser.setId(1318349262742675458L);user.setName(" Pay attention to my WeChat official account ");user.setAge(18);//  Be careful : updateById  But the parameter is a   object int i = userMapper.updateById(user);System.out.println(i);}

 Insert picture description here

be-all sql They are automatically configured for you dynamically !

4. Auto fill

Creation time 、 Modification time ! These operations are usually done automatically , We don't want to manually update !

Alibaba Development Manual : All the database tables :gmt_create、gmt_modified Almost all tables have to be configured ! And it needs to be automated !

Mode one : Database level ( You are not allowed to modify the database at work )

  1. Add fields to the table create_time,update_time

     Insert picture description here

  2. Test the insertion method again , We need to synchronize entity classes first

    private Date createTime;private Date updateTime;
  3. Check the update result again

     Insert picture description here

Mode two : Code level

  1. Delete the default value in the database 、 update operation

     Insert picture description here

  2. Annotations need to be added to the field attributes of the entity class

    // Fields add padding @TableField(fill = FieldFill.INSERT)private Date createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;
  3. Write a processor to handle the annotation

    package com.zhy.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 IOC In the container public class MyMetaObjectHandler implements MetaObjectHandler {//  The filling strategy when inserting @Overridepublic 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);}//  Fill strategy when updating @Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill ...");this.setFieldValByName("updateTime", new Date(), metaObject);}}
  4. Test insert

  5. Test update , Observation time

5. Optimism lock

During the interview , We are often asked about the optimistic lock , Pessimistic locking .

Optimism lock : seeing the name of a thing one thinks of its function , It always thinks there won't be a problem , No matter what you do, don't lock it ! If something goes wrong , Update the value test again !

Pessimistic locking : seeing the name of a thing one thinks of its function , It always thinks there's going to be a problem , Lock up whatever you do ! To operate again !

Optimistic lock implementation :

  • When taking out the record , Get current version
  • update , Take this with you version
  • On update , set version = newVersion where version = oldVersion
  • If version incorrect , Failed to update
 Optimism lock :1、 First query , Get version number  version = 1-- Aupdate user set name = "zhy", version = version + 1where id = 2 and version = 1-- B  Thread force finish first , This is the time  version = 2, It can lead to A Modification failed update user set name = "zhy", version = version + 1where id = 2 and version = 1

Test it MyBatisPlus Plug in for :

  1. Add one to the database version Field

     Insert picture description here

  2. You need to add the corresponding fields to the entity class

    @Version //  Optimistic lock version annotation private Integer version;
  3. Certified components

    //  Scan our  mapper Folder @MapperScan("com.zhy.mapper")@EnableTransactionManagement@Configurationpublic class MyBatisPlusConfig {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();// Optimism lock mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return mybatisPlusInterceptor;}
  4. Test it

        //  Test optimistic lock successfully @Testpublic void testVersionSuccess(){// 1.  Query user information User user = userMapper.selectById(1L);// 2.  Modify user information user.setName("zhy");user.setAge(24);// 3.  Perform an update operation userMapper.updateById(user);}//  Failed to test optimistic lock ! Multithreading @Testpublic void testVersionFall(){//  Threads 1User user1 = userMapper.selectById(1L);user1.setName("zhy111");user1.setAge(14);//  Threads 2User user2 = userMapper.selectById(1L);user2.setName("zhy222");user2.setAge(24);userMapper.updateById(user2);// Spinlock to multiple attempts to commit !userMapper.updateById(user1); // If there is no optimistic lock, the value of the queue skipping thread will be overridden }}
  5. test result

     Insert picture description here

6. Query operation

//  Test the query @Testpublic void testSelectById(){User user = userMapper.selectById(1);System.out.println(user);}//  Batch query @Testpublic void testSelectByBatchIds(){List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));users.forEach(System.out::println);}//  Use one of the conditional queries  map@Testpublic void testSelectByMap(){HashMap<String, Object> map = new HashMap<>();//  Customize to query map.put("name","Zhy");map.put("age","3");List<User> users = userMapper.selectByMap(map);users.forEach(System.out::println);}

7. Paging query

Paging sites are frequently used

  1. Original use limit paging
  2. pageHelper Third party plug-ins
  3. MybatisPlus Built in paging plug-in

How to use ?

  1. Configure interceptors

    @Beanpublic MybatisPlusInterceptor MybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();// Paging configuration mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());return mybatisPlusInterceptor;}
  2. Use it directly Page Object can

    //  Test paging query @Testpublic void testPage(){//  Parameter one :  The current page //  Parameter two :  Page size //  After using the paging plug-in , All paging operations become simple Page<User> page = new Page<>(1,5);userMapper.selectPage(page, null);page.getRecords().forEach(System.out::println);System.out.println(page.getTotal());}

8. Delete operation

//  Test to delete @Testpublic void testDeleteById(){userMapper.deleteById(1318349262742675458L);}//  Test batch delete @Testpublic void testDeleteBatchId(){userMapper.deleteBatchIds(Arrays.asList(1318349262742675460L,1318349262742675461L));}// adopt map Delete @Testpublic void testDeleteByMap(){HashMap<String, Object> map = new HashMap<>();map.put("name","Zhy");userMapper.deleteByMap(map);}

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

9. Logical deletion

Physical delete : Remove directly from the database

Logical deletion : Not removed from the database , It's a variable that makes it work !deleted=0 --> deleted=1

Administrators can view deleted records ! Prevent data loss ! It's like a recycle bin !

test :

  1. Add a... To the database table deleted Field

     Insert picture description here

  2. Add attribute to entity class

    //since 3.3.0, After configuration, you can ignore the annotation on the unconfigured property private Integer deleted;
  3. To configure

    #  The name of the entity field for global logical deletion (since 3.3.0, After configuration, you can ignore the annotation on the unconfigured property )
    mybatis-plus.global-config.db-config.logic-delete-field=deleted
    #  Logical deleted value ( The default is  1)
    mybatis-plus.global-config.db-config.logic-delete-value=1
    #  Logical undeleted value ( The default is  0)
    mybatis-plus.global-config.db-config.logic-not-delete-value=0
  4. Test to delete

     Insert picture description here

  5. Test the query

     Insert picture description here

All of the above CRUD Operations and their extensions , We have to master ! It will greatly improve work efficiency !

Four 、 Performance analysis plug-ins

In our usual development , There will be some slow sql. Solution : test ,druid monitor …

effect : Performance analysis interceptor , Used to output each SQL Statement and its execution time (3.2 External plug-ins are recommended for future versions )

MyBatisPlus It also provides plug-ins for performance analysis , If it exceeds this time, it stops running !

  1. Import plug-ins

    // SQL Execution efficiency plug-ins @Bean@Profile({"dev","test"})public PerformanceInterceptor performanceInterceptor(){PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();performanceInterceptor.setMaxTime(100); //ms  Set up sql Maximum execution time , If it exceeds, it will not be executed performanceInterceptor.setFormat(true); //  Is it formatted return performanceInterceptor;}

    remember , To be in SpringBoot The configuration environment is dev perhaps test Environmental Science !

  2. Test use

    //  Test the query @Testpublic void testSelectById(){User user = userMapper.selectById(3);System.out.println(user);}

    An exception will be thrown as long as it is out of time

Using performance analysis plug-ins can improve efficiency , The new version MP The plug-in has been removed , have access to druid

5、 ... and 、 Conditional constructor

Very important :wrapper

We write complex sql You can use it instead of !

@Testvoid contextLoads() {// Inquire about name Users who are not empty and their mailbox is not empty , Older than or equal to 12QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.isNotNull("name").isNotNull("email").ge("age",12);userMapper.selectList(wrapper).forEach(System.out::println);}@Testvoid test1(){// The query name equals zhy Of QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("name","zhy");User user = userMapper.selectOne(wrapper);System.out.println(user);}@Testvoid test2(){// The age of inquiry is 20-30 Number of users between the ages QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.between("age",20,30);Integer count = userMapper.selectCount(wrapper);System.out.println(count);}@Testvoid test3(){// The query name does not contain eQueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notLike("name","e")//name NOT LIKE %e%.likeRight("email","t");//email LIKE t%List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);maps.forEach(System.out::println);}@Testvoid test4(){//id Found in subquery QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.inSql("id","select id from user where id < 3");List<Object> objects = userMapper.selectObjs(wrapper);objects.forEach(System.out::println);}@Testvoid test5(){// adopt id Sort QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.orderByDesc("id");List<User> userList = userMapper.selectList(wrapper);userList.forEach(System.out::println);}

6、 ... and 、 Code generator

mapper、pojo、service、controller Let the program be written !

AutoGenerator yes MyBatis-Plus Code generator for , adopt AutoGenerator Can be generated quickly Entity、Mapper、Mapper XML、Service、Controller Etc , Greatly improved development efficiency .

What I use here is 3.4.0 Version of , It's different from the previous version , See the official tutorial and do it step by step .

https://baomidou.com/guide/generator.html#%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B