当前位置: 首页 > article >正文

使用mybatis-plus自定义分页实现一对多的分页功能

自定义 Mapper 方法中使用分页

IPage<UserVo> selectPageVo(IPage<?> page, Integer state);
// 或者自定义分页类
MyPage selectPageVo(MyPage page);
// 或者返回 List
List<UserVo> selectPageVo(IPage<UserVo> page, Integer state);

对应的 XML 配置:

<select id="selectPageVo" resultType="xxx.xxx.xxx.UserVo">
    SELECT id,name FROM user WHERE state=#{state}
</select>

如果返回类型是 IPage,则入参的 IPage 不能为 null。如果想临时不分页,可以在初始化 IPage 时 size 参数传入小于 0 的值。 如果返回类型是 List,则入参的 IPage 可以为 null,但需要手动设置入参的 IPage.setRecords(返回的 List)。 如果 XML 需要从 page 里取值,需要使用 page.属性 获取。

特殊需求

有两张表,商品表和商品属性表,具有一对多的关系
需求是:只有当商品存在至少一个价格为0的规格时,该商品才会被筛选出来。同时分页还是基于商品表的分页,但只保留符合条件的商品。

实现方式

在商品分页查询中,通过 EXISTS 子查询筛选出存在价格为 0 的规格的商品

<select id="selectProductPage" resultType="com.example.entity.Product">
    SELECT p.id, p.name, p.price
    FROM product p
    WHERE p.state = #{state}
      AND EXISTS (
          SELECT 1 
          FROM product_spec ps 
          WHERE ps.product_id = p.id 
            AND ps.spec_price = 0 <!-- 筛选存在价格为0的规格 -->
      )
</select>

Service 层查询规格时过滤价格为0,在查询商品规格时,直接过滤出价格为 0 的规格,将商品和商品规格进行组合,实现一对多的关系:

@Service
public class ProductServiceImpl implements ProductService {
    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ProductSpecMapper productSpecMapper;

    @Override
    public PageResult<ProductPageVO> getProductPage(Integer pageNum, Integer pageSize, Integer state) {
        // 1. 分页查询商品表(仅包含有价格为0规格的商品)
        IPage<Product> page = new Page<>(pageNum, pageSize);
        IPage<Product> productPage = productMapper.selectProductPage(page, state);

        // 2. 提取商品ID列表
        List<Long> productIds = productPage.getRecords().stream()
                .map(Product::getId)
                .collect(Collectors.toList());

        if (productIds.isEmpty()) {
            return new PageResult<>(Collections.emptyList(), 0L);
        }

        // 3. 批量查询商品规格(仅价格为0的规格)
        List<ProductSpec> specs = productSpecMapper.selectList(
                new QueryWrapper<ProductSpec>()
                        .in("product_id", productIds)
                        .eq("spec_price", BigDecimal.ZERO) // 直接过滤价格为0
        );

        // 4. 按商品ID分组规格
        Map<Long, List<ProductSpec>> specMap = specs.stream()
                .collect(Collectors.groupingBy(ProductSpec::getProductId));

        // 5. 组装 VO 对象(规格已过滤)
        List<ProductPageVO> voList = productPage.getRecords().stream()
                .map(product -> {
                    ProductPageVO vo = new ProductPageVO();
                    BeanUtils.copyProperties(product, vo);
                    vo.setSpecs(specMap.getOrDefault(product.getId(), Collections.emptyList()));
                    return vo;
                }).collect(Collectors.toList());

        // 6. 返回分页结果
        return new PageResult<>(voList, productPage.getTotal());
    }
}

通过结合 EXISTS 子查询和内存数据组装,既保证了分页的准确性,又高效筛选出符合条件的商品及规格。


http://www.kler.cn/a/583984.html

相关文章:

  • Unity引擎架构介绍及代码示例
  • Nature最新报道:分析四大主流AI工具、性能测评、推荐使用场景
  • Vim忍者速成秘卷:让你的键盘冒出残影の奥义
  • 如何通过ibd文件恢复MySql数据
  • 鸿蒙编译框架插件HvigorPlugin接口的用法介绍
  • 蓝桥杯备考:数据结构堆之 除2!
  • STM32Cubemx-H7-9-串口接受不定长度数据并识别
  • 解决 VSCode SSH 连接报错:“REMOTE HOST IDENTIFICATION HAS CHANGED” 的问题
  • Nginx 多协议代理功能(Nginx Multi Protocol Proxy Function)
  • windows11 LTSC 24h2 访问NAS问题的安全高效解决
  • C语言:计算并输出三个整数的最大值 并对三个数排序
  • 图解AUTOSAR_CP_ServiceDiscovery
  • Unix 域套接字(本地套接字)
  • NLP常见任务专题介绍(4)-ConditionalGeneration和CasualLM区别
  • 关于Playwright和Selenium 的区别和选择
  • nginx部署使用【常用命令】
  • C++时间复杂度详解
  • Blackbox.Ai体验:AI编程插件如何提升开发效率
  • Docker 基础命令 - 以 Nginx 实战总结
  • 在Electron-Vue中实现macOS风格自定义标题栏