AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified Apache-2.0 Self-run

Mybatis Pagehelper Xugudb Adapter

skill-kourou25-xugudb-dev-skills-mybatis-pagehelper-xugudb-adapter · by kourou25

MyBatis PageHelper 分页插件适配虚谷数据库(XuguDB)的完整指南。当用户需要将基于 MyBatis PageHelper 的分页查询配置或适配到虚谷数据库时使用此技能,包括依赖配置、分页配置、查询优化、性能调优等。适用于需要分页查询的 MyBatis 项目。

— No reviews yet
0 installs
36 views
0.0% view→install

Install

$ agentstack add skill-kourou25-xugudb-dev-skills-mybatis-pagehelper-xugudb-adapter

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • ✓ Prompt-injection patterns
  • ✓ Secret / credential exfiltration
  • ✓ Dangerous shell & filesystem operations
  • ✓ Untrusted network calls
  • ✓ Known-malicious package signatures

What it can access

  • ✓ Network access No
  • ✓ Filesystem access No
  • ✓ Shell / process execution No
  • ✓ Environment & secrets No
  • ✓ Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-kourou25-xugudb-dev-skills-mybatis-pagehelper-xugudb-adapter)

Reliability & compatibility

✓ Security review passed
0 installs to date
— no reviews yet
● 3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Mybatis Pagehelper Xugudb Adapter? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

MyBatis PageHelper 分页插件虚谷数据库适配指南

概述

本技能提供 MyBatis PageHelper 分页插件适配虚谷数据库(XuguDB)的完整配置指南。PageHelper 是一个 MyBatis 的物理分页插件,支持多种数据库,现在可以通过配置支持虚谷数据库。

适用场景:

  • MyBatis 项目分页查询
  • 列表数据分页展示
  • 大数据量分页处理
  • 复杂查询分页优化

核心特性:

  • 物理分页,内存占用小
  • 支持多种数据库
  • 支持多种分页方式
  • 支持排序和聚合查询
  • 支持自定义方言
  • 支持 RowBounds 分页
  • 支持 PageHelper 自动 Count 查询

快速开始

1. 添加依赖

Maven 配置:


    
    
        org.mybatis
        mybatis
        3.5.13
    
    
    
    
        org.mybatis
        mybatis-spring
        2.1.1
    
    
    
    
        com.github.pagehelper
        pagehelper
        5.3.2
    
    
    
    
        com.xugu
        xugu-jdbc
        12.0.0
    
    
    
    
        org.mybatis.spring.boot
        mybatis-spring-boot-starter
        2.3.1
    
    
    
    
        com.github.pagehelper
        pagehelper-spring-boot-starter
        1.4.6
    

Gradle 配置:

dependencies {
    implementation 'org.mybatis:mybatis:3.5.13'
    implementation 'org.mybatis:mybatis-spring:2.1.1'
    implementation 'com.github.pagehelper:pagehelper:5.3.2'
    implementation 'com.xugu:xugu-jdbc:12.0.0'
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.3.1'
    implementation 'com.github.pagehelper:pagehelper-spring-boot-starter:1.4.6'
}

2. 配置 PageHelper

MyBatis 配置文件 mybatis-config.xml:


    
        
            
            
            
            
            
            
            
            
            
            
        
    

Spring Boot 配置 application.yml:

# PageHelper 配置
pagehelper:
  helper-dialect: xugudb
  reasonable: true
  support-methods-arguments: true
  params: count=countSql
  page-size-zero: false
  auto-runtime-dialect: true
  auto-dialect: true
  close-conn: true
  count-suffix: _COUNT

# MyBatis 配置
mybatis:
  config-location: classpath:mybatis-config.xml
  mapper-locations: classpath:mapper/**/*.xml
  type-aliases-package: com.example.entity
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: true
    lazy-loading-enabled: true
    aggressive-lazy-loading: false

3. 创建实体类

package com.example.entity;

import java.time.LocalDateTime;

public class User {
    private Long id;
    private String name;
    private String email;
    private String phone;
    private Integer status;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
    
    // Getters and Setters
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    public String getPhone() { return phone; }
    public void setPhone(String phone) { this.phone = phone; }
    
    public Integer getStatus() { return status; }
    public void setStatus(Integer status) { this.status = status; }
    
    public LocalDateTime getCreatedAt() { return createdAt; }
    public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
    
    public LocalDateTime getUpdatedAt() { return updatedAt; }
    public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
}

4. 创建 Mapper 接口

package com.example.mapper;

import com.example.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;

@Mapper
public interface UserMapper {
    
    // 查询所有用户
    @Select("SELECT * FROM users")
    List findAll();
    
    // 根据状态查询用户
    @Select("SELECT * FROM users WHERE status = #{status}")
    List findByStatus(@Param("status") Integer status);
    
    // 根据名称模糊查询
    @Select("SELECT * FROM users WHERE name LIKE CONCAT('%', #{name}, '%')")
    List findByNameLike(@Param("name") String name);
    
    // 复杂查询
    @Select("SELECT * FROM users WHERE status = #{status} AND name LIKE CONCAT('%', #{name}, '%') ORDER BY created_at DESC")
    List findByStatusAndNameLike(@Param("status") Integer status, @Param("name") String name);
    
    // 聚合查询
    @Select("SELECT COUNT(*) FROM users WHERE status = #{status}")
    long countByStatus(@Param("status") Integer status);
}

5. 创建 Mapper XML 文件

UserMapper.xml:


    
    
    
        
        
        
        
        
        
        
    
    
    
    
        SELECT * FROM users
    
    
    
    
        SELECT * FROM users WHERE status = #{status}
    
    
    
    
        SELECT * FROM users WHERE name LIKE CONCAT('%', #{name}, '%')
    
    
    
    
        SELECT * FROM users 
        WHERE status = #{status} 
        AND name LIKE CONCAT('%', #{name}, '%') 
        ORDER BY created_at DESC
    
    
    
    
        SELECT COUNT(*) FROM users WHERE status = #{status}
    
    

分页查询

1. 基础分页查询

使用 PageHelper.startPage():

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.example.mapper.UserMapper;
import com.example.entity.User;
import java.util.List;

public class UserService {
    
    private UserMapper userMapper;
    
    /**
     * 分页查询用户
     * @param pageNum 页码(从1开始)
     * @param pageSize 每页大小
     * @return 分页结果
     */
    public PageInfo getUsersByPage(int pageNum, int pageSize) {
        // 设置分页参数
        PageHelper.startPage(pageNum, pageSize);
        
        // 执行查询(会被自动分页)
        List users = userMapper.findAll();
        
        // 获取分页信息
        PageInfo pageInfo = new PageInfo<>(users);
        
        return pageInfo;
    }
    
    /**
     * 带条件的分页查询
     * @param status 状态
     * @param name 名称
     * @param pageNum 页码
     * @param pageSize 每页大小
     * @return 分页结果
     */
    public PageInfo getUsersByCondition(Integer status, String name, int pageNum, int pageSize) {
        // 设置分页参数
        PageHelper.startPage(pageNum, pageSize);
        
        // 执行查询
        List users = userMapper.findByStatusAndNameLike(status, name);
        
        // 获取分页信息
        PageInfo pageInfo = new PageInfo<>(users);
        
        return pageInfo;
    }
}

2. 使用 PageInfo 获取分页信息

public void printPageInfo(PageInfo pageInfo) {
    System.out.println("当前页: " + pageInfo.getPageNum());
    System.out.println("每页大小: " + pageInfo.getPageSize());
    System.out.println("总记录数: " + pageInfo.getTotal());
    System.out.println("总页数: " + pageInfo.getPages());
    System.out.println("是否有上一页: " + pageInfo.isHasPreviousPage());
    System.out.println("是否有下一页: " + pageInfo.isHasNextPage());
    System.out.println("上一页页码: " + pageInfo.getPrePage());
    System.out.println("下一页页码: " + pageInfo.getNextPage());
    System.out.println("是否第一页: " + pageInfo.isIsFirstPage());
    System.out.println("是否最后一页: " + pageInfo.isIsLastPage());
    System.out.navigatepageNums: " + java.util.Arrays.toString(pageInfo.getNavigatepageNums()));
    
    // 获取数据列表
    List users = pageInfo.getList();
    for (User user : users) {
        System.out.println("用户: " + user.getName());
    }
}

3. 使用 RowBounds 分页

import org.apache.ibatis.session.RowBounds;
import java.util.List;

public List getUsersByRowBounds(int offset, int limit) {
    RowBounds rowBounds = new RowBounds(offset, limit);
    return userMapper.findAllWithRowBounds(rowBounds);
}

4. 使用 Lambda 表达式

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import java.util.List;

public PageInfo getUsersByLambda(int pageNum, int pageSize) {
    // 使用 Lambda 表达式
    return PageHelper.startPage(pageNum, pageSize)
        .doSelectPageInfo(() -> userMapper.findAll());
}

// 或者使用更简洁的方式
public PageInfo getUsersByLambda2(int pageNum, int pageSize) {
    return PageHelper.startPage(pageNum, pageSize)
        .doSelectPageInfo(() -> userMapper.findByStatus(1));
}

高级配置

1. 自定义虚谷数据库方言

创建自定义方言类:

package com.example.dialect;

import com.github.pagehelper.dialect.helper.AbstractHelperDialect;
import org.apache.ibatis.cache.CacheKey;

public class XuguDBDialect extends AbstractHelperDialect {
    
    @Override
    public String getPageSql(String sql, Page page, CacheKey pageKey) {
        StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);
        sqlBuilder.append(sql);
        
        if (page.getStartRow() == 0) {
            sqlBuilder.append(" LIMIT ");
            sqlBuilder.append(page.getPageSize());
        } else {
            sqlBuilder.append(" LIMIT ");
            sqlBuilder.append(page.getStartRow());
            sqlBuilder.append(", ");
            sqlBuilder.append(page.getPageSize());
        }
        
        return sqlBuilder.toString();
    }
    
    @Override
    public Object processPageParameter(Mapped ms, Object parameterObject, RowBounds rowBounds, CacheKey pageKey) {
        pageKey.update(rowBounds.getOffset());
        pageKey.update(rowBounds.getLimit());
        return parameterObject;
    }
}

注册自定义方言:


    
        
        
        
        
    

2. 分页合理化配置

// 启用分页合理化
PageHelper.startPage(pageNum, pageSize, true);

// 或者在配置中设置
// reasonable=true 时,如果 pageNum  总页数,查询最后一页

3. 全局配置

Spring Boot 配置:

pagehelper:
  # 数据库方言
  helper-dialect: xugudb
  # 分页合理化
  reasonable: true
  # 是否支持接口参数来传递分页参数
  support-methods-arguments: true
  # 为了支持startPage(Object params)方法
  params: count=countSql
  # 当页数为0时是否查询全部
  page-size-zero: false
  # 是否自动识别数据库方言
  auto-runtime-dialect: true
  # 是否自动检测数据库类型
  auto-dialect: true
  # 关闭连接
  close-conn: true
  # count 查询后缀
  count-suffix: _COUNT

4. 多数据源配置

import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DataSourceConfig {
    
    @Bean
    public PageInterceptor pageInterceptor() {
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("helperDialect", "xugudb");
        properties.setProperty("reasonable", "true");
        properties.setProperty("supportMethodsArguments", "true");
        pageInterceptor.setProperties(properties);
        return pageInterceptor;
    }
    
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource, PageInterceptor pageInterceptor) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setPlugins(pageInterceptor);
        return sessionFactory.getObject();
    }
}

查询优化

1. 避免全表扫描

问题:分页查询时,如果 ORDER BY 字段没有索引,会导致全表扫描。

解决方案:

-- 为排序字段创建索引
CREATE INDEX idx_users_created_at ON users(created_at);
CREATE INDEX idx_users_status ON users(status);

-- 使用覆盖索引
CREATE INDEX idx_users_covering ON users(status, created_at, name, email);

2. 优化 COUNT 查询

问题:复杂的 COUNT 查询可能很慢。

解决方案:

// 使用简化的 COUNT 查询
public long countUsers(Integer status) {
    // 使用 @Select 注解的简化查询
    return userMapper.countByStatus(status);
}

// 或者使用缓存
@Cacheable(value = "userCount", key = "#status")
public long countUsersWithCache(Integer status) {
    return userMapper.countByStatus(status);
}

3. 使用子查询优化

问题:大数据量分页时,LIMIT offset, limit 性能差。

解决方案:


    SELECT u.* FROM users u
    INNER JOIN (
        SELECT id FROM users 
        WHERE status = #{status}
        ORDER BY created_at DESC
        LIMIT #{offset}, #{limit}
    ) t ON u.id = t.id

4. 使用游标分页

问题:传统分页在深页时性能差。

解决方案:

// 使用游标分页(基于上一页最后一条记录)
public PageInfo getUsersByCursor(Long lastId, int pageSize) {
    PageHelper.startPage(1, pageSize);
    
    List users = userMapper.findUsersAfterId(lastId);
    
    return new PageInfo<>(users);
}

// Mapper 方法
@Select("SELECT * FROM users WHERE id > #{lastId} ORDER BY id ASC LIMIT #{limit}")
List findUsersAfterId(@Param("lastId") Long lastId);

性能测试

1. 测试脚本

创建性能测试类:

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
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
public class PageHelperPerformanceTest {
    
    @Autowired
    private UserMapper userMapper;
    
    @Test
    public void testPaginationPerformance() {
        int[] pageSizes = {10, 20, 50, 100};
        int[] pageNumbers = {1, 10, 100, 1000};
        
        for (int pageSize : pageSizes) {
            for (int pageNum : pageNumbers) {
                long startTime = System.currentTimeMillis();
                
                PageHelper.startPage(pageNum, pageSize);
                List users = userMapper.findAll();
                PageInfo pageInfo = new PageInfo<>(users);
                
                long endTime = System.currentTimeMillis();
                long duration = endTime - startTime;
                
                System.out.printf("页码: %d, 每页大小: %d, 耗时: %d ms, 总记录数: %d%n",
                    pageNum, pageSize, duration, pageInfo.getTotal());
            }
        }
    }
    
    @Test
    public void testCountPerformance() {
        long startTime = System.currentTimeMillis();
        
        long count = userMapper.countByStatus(1);
        
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;
        
        System.out.printf("COUNT 查询耗时: %d ms, 结果: %d%n", duration, count);
    }
}

2. 性能监控

添加性能监控:

import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisConfig {
    
    @Bean
    public Interceptor pageInterceptor() {
        PageInterceptor pageInterceptor = new PageInterceptor();
        Properties properties = new Properties();
        properties.setProperty("helperDialect", "xugudb");
        properties.setProperty("reasonable", "true");
        properties.setProperty("supportMethodsArguments", "true");
        
        // 启用性能监控
        properties.setProperty("countSuffix", "_COUNT");
        properties.setProperty("autoRuntimeDialect", "true");
        
        pageInterceptor.setProperties(properties);
        return pageInterceptor;
    }
}

集成测试

1. 单元测试

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Arrays;
import java.util.List;

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
    
    @Mock
    private UserMapper userMapper;
    
    @InjectMocks
    private UserService userService;
    
    private List mockUsers;
    
    @BeforeEach
    void setUp() {
        mockUsers = Arrays.asList(
            createUser(1L, "张三", "zhangsan@example.com"),
            createUser(2L, "李四", "lisi@example.com"),
            createUser(3L, "王五", "wangwu@example.com")
        );
    }
    
    @Test
    void testGetUsersByPage() {
        // 模拟 Mapper 返回
        when(userMapper.findAll()).thenReturn(mockUsers);
        
        // 执行分页查询
        PageInfo pageInfo = userService.getUsersByPage(1, 10);
        
        // 验证结果
        assertNotNull(pageInfo);
        assertEquals(3, pageInfo.getList().size());
        assertEquals(1, pageInfo.getPageNum());
        assertEquals

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [kourou25](https://github.com/kourou25)
- **Source:** [kourou25/xugudb-dev-skills](https://github.com/kourou25/xugudb-dev-skills)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.