首页 > 其他分享 >没用好mybatisplus的Wrapper,我真难为情啊

没用好mybatisplus的Wrapper,我真难为情啊

时间:2022-11-30 22:57:53浏览次数:45  
标签:queryWrapper mybatisplus 难为情 Wrapper queryWrapperClone page prePageDto

背景

我们的springboot应用程序的持久层,是用jeecgboot框架生成的代码。mybatisplus版本是3.1.2。

 

在一次对当前程序的sql性能优化时,我重写了BaseMapper的selectPage方法。其中,为Wrapper<T>参数加上了id限制,以提高sql执行性能。

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface SbhPlatOrderMapper extends BaseMapper<SbhPlatOrder> {    

    @Override
    default IPage<SbhPlatOrder> selectPage(IPage<SbhPlatOrder> page, @Param(Constants.WRAPPER) Wrapper<SbhPlatOrder> queryWrapper){
        PrePageDto prePageDto = selectCountCache(queryWrapper);
        page.setTotal(prePageDto.getRowCount());
        if (prePageDto.getRowCount()>0) {
            if (queryWrapper instanceof LambdaQueryWrapper) {
                ((LambdaQueryWrapper<SbhPlatOrder>) queryWrapper).between(SbhPlatOrder::getId, prePageDto.getMinId(), prePageDto.getMaxId());
            } else if (queryWrapper instanceof QueryWrapper) {
                ((QueryWrapper<SbhPlatOrder>) queryWrapper).lambda().between(SbhPlatOrder::getId, prePageDto.getMinId(), prePageDto.getMaxId());
            }
            page.setRecords(selectPageList((page.getCurrent() - 1) * page.getSize(), page.getSize(), queryWrapper));
        }
        return page;
    }
    
    @Cacheable(cacheNames = RedisConfig.SBH_PLAT_ORDER_COUNT_CACHE_KEY,
            key = "T(com.emax.zhenghe.common.util.security.MD5Util).md5Encode(#queryWrapper.customSqlSegment)")
    PrePageDto selectCountCache(@Param(Constants.WRAPPER) Wrapper<SbhPlatOrder> queryWrapper);

    。。。
}

 

问题描述

程序上线后运行了一段时间。后来,发现了一个问题。见下面日志截图

 

 

原来呢,service类里调用这个分页的方法里,并不是每次调用分页时都new一个Wrapper对象,而是重复使用一个Wrapper对象。 所以,出现上图的问题就不难理解了。

 

 

 

解决办法 -Wrapper#getCustomSqlSegment

头疼医头的方式,是修改service类里调用这个分页的方法,每次调用分页前都new一个Wrapper对象。

显然,这样解决问题只是一时。以后再有调用这个分页的地方,依然会存在这个问题呀。

所以,我的解决办法是利用 Wrapper#getCustomSqlSegment, 上面sql里重复出现的是 id BETWEEN。所以,修正的代码如下:

    // 外面调用处可能复用这个queryWrapper对象。所以,为避免重复追加条件,这里先做判读再追加。
    if (!queryWrapper.getCustomSqlSegment().contains("id BETWEEN")) {
        if (queryWrapper instanceof LambdaQueryWrapper) {
            ((LambdaQueryWrapper<SbhPlatOrder>) queryWrapper).between(SbhPlatOrder::getId, prePageDto.getMinId(), prePageDto.getMaxId());
        } else if (queryWrapper instanceof QueryWrapper) {
            ((QueryWrapper<SbhPlatOrder>) queryWrapper).lambda().between(SbhPlatOrder::getId, prePageDto.getMinId(), prePageDto.getMaxId());
        }
    }

 

更好的解决办法-Wrapper#clone

利用clone方法。mybatisplus的Wrapper的抽象父类AbstractWrapper,重写了超类Object的clone方法。如下是源码:

package com.baomidou.mybatisplus.core.conditions;
public abstract class AbstractWrapper ...{ @Override @SuppressWarnings("all") public Children clone() { return SerializationUtils.clone(typedThis); } }

相比上面的解决办法,我认为这是更好的解决办法,这样修正的代码如下:

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface SbhPlatOrderMapper extends BaseMapper<SbhPlatOrder> {    

    @Override
    default IPage<SbhPlatOrder> selectPage(IPage<SbhPlatOrder> page, @Param(Constants.WRAPPER) Wrapper<SbhPlatOrder> queryWrapper){
        Wrapper<SbhPlatOrder> queryWrapperClone = queryWrapper.clone();
        PrePageDto prePageDto = selectCountCache(queryWrapperClone);
        page.setTotal(prePageDto.getRowCount());
        if (prePageDto.getRowCount()>0) {
            if (queryWrapperClone instanceof LambdaqueryWrapperClone) {
                ((LambdaQueryWrapper<SbhPlatOrder>) queryWrapperClone).between(SbhPlatOrder::getId, prePageDto.getMinId(), prePageDto.getMaxId());
            } else if (queryWrapperClone instanceof QueryWrapper) {
                ((QueryWrapper<SbhPlatOrder>) queryWrapperClone).lambda().between(SbhPlatOrder::getId, prePageDto.getMinId(), prePageDto.getMaxId());
            }
            page.setRecords(selectPageList((page.getCurrent() - 1) * page.getSize(), page.getSize(), queryWrapperClone));
        }
        return page;
    }

    。。。
}

 

EOF-thanks!

标签:queryWrapper,mybatisplus,难为情,Wrapper,queryWrapperClone,page,prePageDto
From: https://www.cnblogs.com/buguge/p/16940068.html

相关文章

  • 由querywrapper使用不当导致的两个错误
    QueryWrapper<Invoice>queryWrapper=newQueryWrapper<>(invoice);Page<Invoice>page=newPage<Invoice>(invoice.getPageNo(),invoice.getPageSize());queryWrap......
  • MybatisPlus 删除记录
    转自:https://blog.csdn.net/h470789634/article/details/124573252学习目标:mybatisplus的删除操作学习内容:delete使用学习产出:1、deleteById@Test   voiddeleteTes......
  • Java开发学习(四十五)----MyBatisPlus查询语句之映射匹配兼容性
    1、映射匹配兼容性我们已经能从表中查询出数据,并将数据封装到模型类中,这整个过程涉及到一张表和一个模型类:之所以数据能够成功的从表中获取并封装到模型对象中,原因是表......
  • MybatisPlus查询小例子
    @OverridepublicPageUtilsqueryBaseAttrPage(Map<String,Object>params,LongcatelogId){QueryWrapper<AttrEntity>queryWrapper=newQueryWrapper<>();i......
  • Vue项目“TypeError: Cannot read property ‘_wrapper’ of undefined
    前情最近在开发一个H5营销活动项目,为了更高的开发效率我使用了Vue全家桶来实现。坑位在开发中遇到一个奇怪报错(报错截图如下),从提示看也定位不到是哪里出问题Why?......
  • SpringBoot整合MybatisPlus实现分页功能
    首先,展示一下项目的主题:  创建数据库,放入一些数据,方便我们接下来的功能演示: 接下来,我们创建一个实体类,然后写对应的接口:packagecom.example.domain;importlo......
  • Java: Wrapper Classes
    Wrapperclassesprovideawaytouseprimitivedatatypes(int, boolean,etc..)asobjects.PrimitiveDataTypeWrapperClassbyteByteshortShortint......
  • Java开发学习(四十四)----MyBatisPlus查询语句之查询条件
    1、查询条件前面我们只使用了lt()和gt(),除了这两个方法外,MybatisPlus还封装了很多条件对应的方法。MybatisPlus的查询条件有很多:范围匹配(>、=、between)模糊匹......
  • mybatisPlus笔记
    MybatisPlus:一些容易不知道是什么含义的方法:MybaitsPlus中我们没有进行设置表名,MybaitsPlus是如何进行确定表名的?​MybatisPlus中默认是通过实体类(Ma......
  • MybatisPlus的一些高级特性
    1、MybatisPlus多数据源配合导入相关依赖<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</vers......