1, Introduction to MybatisPlus
MyBatis plus (opens new window) (MP for short) is an enhancement tool of MyBatis (opens new window). Based on MyBatis, it only makes enhancement without change, and is born to simplify development and improve efficiency. Mybatis plus Chinese document
characteristic:
1. No invasion: it is only enhanced without change, and its introduction will not affect the existing project, which is as smooth as silk
2. Low loss: the basic CURD will be injected automatically upon startup, with basically no loss of performance and direct object-oriented operation
3. 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 needs
4. Support calling in Lambda form: it is convenient to write various query conditions through Lambda expression, and there is no need to worry about wrong fields
5. Support automatic generation of primary key: support up to four primary key policies (including distributed unique ID generator - Sequence), which can be configured freely to perfectly solve the primary key problem
6. Support ActiveRecord mode: support ActiveRecord formal calls. Entity classes only need to inherit the Model class to perform powerful CRUD operations
7. Support custom global general operations: support global general method injection (Write once, use anywhere)
8. 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
9. 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
10. The paging plug-in supports multiple databases: MySQL, MariaDB, Oracle, DB2, H2, HSQL, SQLite, Postgre, SQLServer and other databases
11. 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
12. 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
Custom code generator MyCodeGenerator
Some steps in project construction are repetitive, such as creating an Entity according to the database table, and then creating its related Mapper, Mapper.xml, Service, Controller and other module files. These complicated and repeated steps are not beneficial to our programming. In order to liberate our hands and reduce these repetitive tasks, MP provides us with a code generator to help us quickly build the project structure.
To use the code generator, first import the following dependencies:
<!--Code generator dependency--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.4.1</version> </dependency> <!--Template engine dependency--> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.0</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency>
After the dependency import is completed, we need to write our own generator implementation. The following code can be adjusted according to your own needs. After modification, run the program.
public class MyCodeGenerator { public static void main(String[] args) { //1. Global configuration GlobalConfig globalConfig = new GlobalConfig(); String projectPath = System.getProperty("user.dir");//Current project directory globalConfig.setAuthor("wsl") //author .setActiveRecord(true) //Is AR mode supported .setOutputDir(projectPath + "/src/main/java") //Build path .setFileOverride(false) //Overwrite .setIdType(IdType.AUTO) //Primary key policy .setServiceName("%sService") //%s is the name of the Service interface used to generate prefixed with I .setBaseResultMap(true) .setBaseColumnList(true); //2. Data source configuration DataSourceConfig dbConfig = new DataSourceConfig(); dbConfig.setDriverName("com.mysql.cj.jdbc.Driver") //Set database driver .setUrl("jdbc:mysql://localhost:3306/mybatis?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=GMT%2B8") .setUsername("root").setPassword("123456") .setDbType(DbType.MYSQL); //Set database type //3. Policy configuration StrategyConfig strategyConfig = new StrategyConfig(); // Auto fill configuration ArrayList<TableFill> tableFills = new ArrayList<>(); TableFill updateTime = new TableFill("updateTime", FieldFill.INSERT_UPDATE); tableFills.add(updateTime); strategyConfig.setInclude("blog") //Generated table .setCapitalMode(true) //Global uppercase naming .setNaming(NamingStrategy.underline_to_camel) //Naming strategy of database tables insinuating to entities .setEntityLombokModel(true) //Automatic lombok .setLogicDeleteFieldName("deleted") //Logical deletion .setVersionFieldName("version") //Optimistic lock .setControllerMappingHyphenStyle(true) // .setRestControllerStyle(true) .setTableFillList(tableFills); //Auto fill configuration //4. Package name policy configuration PackageConfig pkConfig = new PackageConfig(); pkConfig.setParent("com.kuang") //Parent package .setMapper("mapper") .setService("service") .setController("controller") .setEntity("pojo") .setXml("mapper") .setModuleName("blog"); //5. Integrated configuration AutoGenerator autoGenerator = new AutoGenerator(); autoGenerator.setGlobalConfig(globalConfig) .setDataSource(dbConfig) .setStrategy(strategyConfig) .setPackageInfo(pkConfig); //6. Implementation autoGenerator.execute(); } }
Plug in configuration
Introduction to MP plug-in
1. PaginationInnerInterceptor
2. SQL execution analysis plug-in BlockAttackInnerInterceptor (malicious full table update and deletion by the organization)
3. Optimistic lock plug-in optisticlockerinnerinterceptor (when a record is to be updated, I hope it has not been updated by others)
MP integration SpringBoot
Integration dependence
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3.2</version> </dependency>
Environment configuration
# apply name spring.application.name=mybatis_plus # Application service WEB access port server.port=8080 #Connection field spring.datasource.username=root spring.datasource.password=123456 # You need to set the time zone to use mysql version above 8.0 spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
Entity class
package com.kuang.pojo; import lombok.AllArgsConstructr; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class User { private Integer id; private String name; private String pwd; private String perm; }
Write mapper
package com.kuang.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.kuang.pojo.User; import org.springframework.stereotype.Repository; // Inherit the basic class BaseMapper on the corresponding Mapper @Repository//Represents the persistence layer public interface UserMapper extends BaseMapper<User> { //All CRUD operations have been written //You don't need to configure a lot of files as before! }
Scan the mapper
package com.kuang; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @MapperScan("com.kuang.mapper") @SpringBootApplication public class MybatisPlus02Application { public static void main(String[] args) { SpringApplication.run(MybatisPlus02Application.class, args); } }
Test query
package com.kuang; import com.kuang.mapper.UserMapper; import com.kuang.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.List @SpringBootTest class MybatisPlus02ApplicationTests { @Autowired private UserMapper userMapper; @Test void contextLoads() { List<User> userList = userMapper.selectList(null); for (User user : userList) { System.out.println(user); } } }
Optimistic lock handling
Optimistic lock: as the name suggests, it always thinks that there will be no problem. No matter what you do, don't lock it! If there is a problem, update the value test again!
Pessimistic lock: as the name suggests, it is very pessimistic. It always thinks that there are always problems. It will lock no matter what it does! Do it again!
Implementation of optimistic lock: first query the information of the object with version data (very important), then use it, and then modify it based on this object.
Example:
Annotate the version field
@Version private Integer version;
Configure plug-ins and inject implementation.
@MapperScan("com.kuang.mapper") @EnableTransactionManagement @Configuration public class MybatisPlusConfig { /** * new edition */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return mybatisPlusInterceptor; } }
After modification, the version field will be incremented automatically.
userMapper.updateById(user);
Possible problems of optimistic lock
User user = userMapper.selectById(22); user.setName("Niu Niu"); user.setPerm("1"); //Simulate another thread queue jumping User user2 = userMapper.selectById(22); user2.setName("Niu Niu"); user2.setPerm("2"); userMapper.updateById(user2); userMapper.updateById(user); //The final result shows that only one version is added because the previous one is overwritten.
Logical deletion
When deleting table records in a database, we often use logical deletion, that is, changing the state of a record to limit it. Usually, a status field is added to each record, and 0 or 1 is used to represent its status (here it indicates whether to delete it). Using logical deletion also avoids the risk of losing important data.
MP provides us with automatic implementation of SQL statements of a series of operation tables. We can configure logical deletion through @ TableLogic.
Example:
Add the @ TableLogic annotation to the logically deleted field
@TableLogic private Integer deleted;
Configure logically deleted fields and status values
# Global logically deleted entity field name (since 3.3.0, it can be ignored after configuration, and step 2 is not configured) mybatis-plus.global-config.db-config.logic-delete-field=deleted #Logical deleted value (default is 1) mybatis-plus.global-config.db-config.logic-delete-value=1 # Logical undeleted value (0 by default) mybatis-plus.global-config.db-config.logic-not-delete-value=0
After the configuration is successful, the deletion method of MP is used for logical deletion
userMapper.deleteById(22);
Note: the statements after logical deletion will not be queried by the mybatis plus method. You need to customize SQL to view them.
Log function
The log function of MP can view the generated SQL statements
Add logging support to the SpringBoot project
# Log output mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
Add logging support to the spring MVC project
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- Global parameters --> <settings> <!--Set log function--> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> </configuration>
Auto fill field
When using MP to insert or add data, we can add some default fill values to it.
For example, the following automatically populates the creation time and update time of the object
1. Add @ TableField annotation on the field to be filled automatically, and set the fill property to FieldFill.INSERT or FieldFill.INSERT during insertion_ Update is populated when inserted or updated.
//Auto fill time on insertion @TableField(fill = FieldFill.INSERT) private Date createTime; //Auto fill time on insert or update @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime;
2. Customize the implementation class of a meta object processor interface and inject it into the IOC container
@Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // Starting version 3.3.0 (recommended) // perhaps this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // Starting version 3.3.3 (recommended) // perhaps this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // It can also be used (there is a bug in this method in 3.3.0) } @Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, "modify_time", LocalDateTime.class, LocalDateTime.now()); // Starting version 3.3.0 (recommended) // perhaps this.strictUpdateFill(metaObject, "modity_time", () -> LocalDateTime.now(), LocalDateTime.class); // Starting version 3.3.3 (recommended) // perhaps this.fillStrategy(metaObject, "modity_time", LocalDateTime.now()); // It can also be used (there is a bug in this method in 3.3.0) } }
The Spring project is assembled in the configuration file (the following steps can be omitted in the SpringBoot project)
<!-- Use here MP Provided sqlSessionFactory,It's done Spring And MP Integration of --> <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="plugins"> <list> <!-- Register paging plug-in --> <bean class="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"></bean> </list> </property> <property name="globalConfig" ref="globalConfig"/> </bean> <!--Configure automatic injection time class--> <bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig"> <property name="metaObjectHandler"> <bean class="com.zktr.handler.MyMetaObjectHandler"/> </property> </bean>