Introduction
MyBatis-Plus (opens new window) (MP for short) is anenhanced tool for MyBatis (opens new window) . On the basis of MyBatis, only enhancements are made without changes, and it was born to simplify development and improve efficiency.
characteristic
No intrusion : only enhancement and no change, the introduction of it will not affect the existing project, as smooth as silk
Low loss : the basic CURD will be automatically injected when it is started, the performance is basically lossless, and the object-oriented operation is directly performed
Powerful CRUD operations : Built-in general Mapper and general Service, most of the CRUD operations on a single table can be realized with only a small amount of configuration, and there is a powerful condition constructor to meet various usage needs
Support Lambda form call : through Lambda expressions, it is convenient to write various query conditions, no need to worry about field typos
Supports automatic primary key generation : supports up to 4 primary key strategies (including a distributed unique ID generator - Sequence), which can be freely configured to perfectly solve the primary key problem
Support ActiveRecord mode : support ActiveRecord form call, the entity class only needs to inherit the Model class to perform powerful CRUD operations
Support custom global general operations : support global general method injection ( Write once, use anywhere )
Built-in code generator : use code or Maven plug-in to quickly generate Mapper, Model, Service, Controller layer code, support template engine, and more custom configurations are waiting for you to use
Built-in paging plug-in : Based on MyBatis physical paging, developers don't 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 : supports 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, which can quickly find out slow queries
Built-in global interception plug-in : Provides intelligent analysis and blocking of delete and update operations on the entire table, and can also customize interception rules to prevent misoperations
support database
Any database that can use MyBatis for CRUD and supports standard SQL, the specific support is as follows, if not in the list below, check the pagination part of the tutorial PR for your support.
MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss ,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb,informix,TDengine,redshift
Dameng Database, Xugu Database, Renmin University Jincang Database, Nanda General (Huaku) Database, Nanda General Database, Shentong Database, Hangao Database, Youxuan Database
quick start
add dependencies
The new MyBatis-Plus 3.0 version is based on JDK8 and provides lambda calls, so the requirements for installing and integrating MP3.0 are as follows:
JDK 8+
Maven or Gradle
Spring Boot project
maven:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>最新版本</version>
</dependency>
Spring project
maven:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>最新版本</version>
</dependency>
configuration
Add the relevant configuration of the H2 database in the application.yml configuration file:
# DataSource Config
spring:
datasource:
driver-class-name: org.h2.Driver
schema: classpath:db/schema-h2.sql
username: root
password: test
sql:
init:
schema-locations: classpath:db/schema-h2.sql
data-locations: classpath:db/data-h2.sql
Add the @MapperScan annotation to the Spring Boot startup class to scan the Mapper folder:
@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Pages
method one:
Use the Service page interface of mybatis-plus
@GetMapping("/pageList")
@ApiOperation(value = "分页列表", notes = "query和user")
public R<IPage<User>> pageList(@ApiIgnore User user, Query query) {
//无条件分页
IPage<User> pages = userService.page(Condition.getPage(query));
//有条件分页
IPage<User> pages = userService.page(Condition.getPage(query), Wrappers.lambdaQuery(user));
return R.data(pages);
}
Method 2:
Custom sql pagination
Controller layer code:
@GetMapping("/pageList")
@ApiOperation(value = "分页列表", notes = "query和user")
public R<IPage<User>> pageList(@ApiIgnore User user, Query query) {
IPage<User> pages = userService.selectUserPage(Condition.getPage(query), user);
return R.data(pages);
}
Call the custom paging sql mapper method in the service
@Override
public IPage<User> selectUserPage(IPage<User> page, User user) {
return page.setRecords(baseMapper.selectUserPage(page, user));
}
Define the mapper paging interface:
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.gis.spacedata.bladex.domain.entity.system.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.List;
public interface UserMapper extends BaseMapper<User> {
List<User> selectUserPage(IPage<User> page, @Param("user") User user);
}
mybatis xml:
<select id="selectUserPage" resultMap="userResultMap">
select * from blade_user where is_deleted = 0
<if test="user.tenantId!=null and user.tenantId != ''">
and tenant_id = #{user.tenantId}
</if>
<if test="user.account!=null and user.account != ''">
and account like CONCAT('%',#{user.account},'%')
</if>
<if test="user.realName!=null and user.realName != ''">
and real_name like CONCAT('%',#{user.realName},'%')
</if>
<if test="user.roleId!=null and user.roleId != ''">
and CAST(#{user.roleId} AS VARCHAR)= ANY(STRING_TO_ARRAY(role_id, ','))
</if>
ORDER BY id
</select>
Condition tool class:
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springblade.core.launch.constant.TokenConstant;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import java.util.Map;
/**
* 分页工具
*
* @author Chill
*/
public class Condition {
/**
* 转化成mybatis plus中的Page
*
* @param query 查询条件
* @return IPage
*/
public static <T> IPage<T> getPage(Query query) {
Page<T> page = new Page<>(Func.toInt(query.getCurrent(), 1), Func.toInt(query.getSize(), 10));
page.setAsc(Func.toStrArray(SqlKeyword.filter(query.getAscs())));
page.setDesc(Func.toStrArray(SqlKeyword.filter(query.getDescs())));
return page;
}
/**
* 获取mybatis plus中的QueryWrapper
*
* @param entity 实体
* @param <T> 类型
* @return QueryWrapper
*/
public static <T> QueryWrapper<T> getQueryWrapper(T entity) {
return new QueryWrapper<>(entity);
}
/**
* 获取mybatis plus中的QueryWrapper
*
* @param query 查询条件
* @param clazz 实体类
* @param <T> 类型
* @return QueryWrapper
*/
public static <T> QueryWrapper<T> getQueryWrapper(Map<String, Object> query, Class<T> clazz) {
Kv exclude = Kv.create().set(TokenConstant.HEADER, TokenConstant.HEADER)
.set("current", "current").set("size", "size").set("ascs", "ascs").set("descs", "descs");
return getQueryWrapper(query, exclude, clazz);
}
/**
* 获取mybatis plus中的QueryWrapper
*
* @param query 查询条件
* @param exclude 排除的查询条件
* @param clazz 实体类
* @param <T> 类型
* @return QueryWrapper
*/
public static <T> QueryWrapper<T> getQueryWrapper(Map<String, Object> query, Map<String, Object> exclude, Class<T> clazz) {
exclude.forEach((k, v) -> query.remove(k));
QueryWrapper<T> qw = new QueryWrapper<>();
qw.setEntity(BeanUtil.newInstance(clazz));
SqlKeyword.buildCondition(query, qw);
return qw;
}
}
Method 3:
Db class using mybatis-plus
illustrate:
Use static calls to execute CRUD methods, avoid Service loop injection in the Spring environment, simplify codes, and improve efficiency
BaseMapper that needs to be injected into the corresponding entity in the project
See the complete usage method: test case(opens new window)
For the parameter Wrapper, Entity or EntityClass needs to be passed in Wrapper to find the corresponding Mapper
It is not recommended to call it in a loop. If it is saved in batches, it is recommended to use Db.saveBatch(data) to save the data after it is constructed
@Test
void testPage() {
IPage<Entity> page = Db.page(new Page<>(1, 1), Entity.class);
Assertions.assertEquals(2, page.getTotal());
page = Db.page(new Page<>(1, 1), Wrappers.lambdaQuery(Entity.class));
Assertions.assertEquals(1, page.getRecords().size());
}
Page pagination plugin
The strange thing is that the data it queries is still all the data, and it does not achieve our paging effect
We all know that the principle of paging is where limit ?,?
That is, just add the where condition after this query statement, we can intercept this statement and add our where condition to it, which is also the withdrawal of the AOP idea (only enhance the original code, no modification)
Plugin body MybatisPlusInterceptor
This plug-in is a core plug-in, which currently proxies Executor#query, Executor#update and StatementHandler#prepare methods
InnerInterceptor
The plug-ins we provide will implement functions based on this interface
Currently available functions:
Automatic pagination: PaginationInnerInterceptor
Multi-tenancy: TenantLineInnerInterceptor
Dynamic table name: DynamicTableNameInnerInterceptor
Optimistic lock: OptimisticLockerInnerInterceptor
sql-properties: IllegalSQLInnerInterceptor
Prevent full table update and deletion: BlockAttackInnerInterceptor
Pagination plugin configuration
Spring transaction, MybatisPlus paging plugin, Mybatis package scanning and other configurations
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* spring事务、MybatisPlus分页插件、mybatis包扫描等配置
*
* @author tarzan liu
* @since JDK1.8
* @date 2021年5月11日
*/
@EnableTransactionManagement
@Configuration
@MapperScan(basePackages = "com.tarzan.**.mapper")
public class MybatisPlusConfig {
/**
* 分页插件
*/
@Bean
public MybatisPlusInterceptor paginationInterceptor() {
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
paginationInnerInterceptor.setMaxLimit(-1L);
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
return mybatisPlusInterceptor;
}
}
In the code, paginationInnerInterceptor.setMaxLimit(-1L); means that there is no limit on the maximum number of pages. By default, the maximum limit is 500 pieces of data per page.