Several ways to write paging in MyBatis-Plus

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

  • 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.

Guess you like

Origin blog.csdn.net/weixin_40986713/article/details/129195211