You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JPA中TypedQuery调用getResultList后removeAll不生效问题求助

问题原因
  • 每次调用typedQuery.getResultList()都会重新执行SQL查询,返回一个全新的结果集合实例。你调用removeAll修改的是第一次调用返回的临时集合,后续再调用getResultList()拿到的是重新从数据库查出来的原始结果,之前的修改完全不生效。
  • 分页参数是在二次过滤之后才设置到typedQuery上的,最后执行查询拿结果的时候,相当于跳过了之前的二次过滤逻辑,直接拿了数据库查询的分页结果。
  • 如果ModelEntity类没有重写equals()和hashCode()方法,removeAll方法会默认按对象内存地址判断是否匹配,也可能导致删除失效。
解决方案

方案1:本地集合二次过滤(兼容所有数据库)

直接把查询结果先存到本地集合,所有过滤、分页操作都在本地集合上执行,避免反复触发数据库查询,修改后代码如下:

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<ModelEntity> query = builder.createQuery(ModelEntity.class);
Root<ModelEntity> root = query.from(ModelEntity.class);

List<Predicate> listWhere = new ArrayList<>();
if(!Strings.isNullOrEmpty(param.getAccountNumber())){
    listWhere.add(builder.like(root.get("accountNumber"), "%"+param.getAccountNumber()+"%"));
}
TypedQuery<ModelEntity> typedQuery = em.createQuery(query
        .where(listWhere.toArray(new Predicate[] {}))
        .orderBy(builder.desc(root.get("createdDate")))
);

// 先执行查询把结果存到本地集合,避免反复调用getResultList
List<ModelEntity> allResult = typedQuery.getResultList();
Integer total = allResult.size();
List<ModelEntity> result = new ArrayList<>();

// 二次过滤逻辑
if(!Strings.isNullOrEmpty(param.getAccountNumber()) && total > 0){
    List<ModelEntity> filteredResult = new ArrayList<>();
    for(ModelEntity data : allResult){
        boolean match = false;
        if (!Strings.isNullOrEmpty(data.getAccountNumber())) {
            List<String> accountNumbers = Arrays.asList(data.getAccountNumber().split(","));
            if(accountNumbers.contains(param.getAccountNumber())){
                match = true;
            }
        }
        if(match){
            filteredResult.add(data);
        }
    }
    allResult = filteredResult;
    total = allResult.size();
}

// 分页逻辑改到本地集合执行
if(total > 0){
    int start = paging.getRowPerPage() * (paging.getPage() - 1);
    int end = Math.min(start + paging.getRowPerPage(), total);
    if(start < total){
        result = allResult.subList(start, end);
    }
}

方案2:数据库层面精准查询(效率更高,以MySQL为例)

如果使用MySQL数据库,可以直接用find_in_set函数在查询时就完成逗号分隔值的精准匹配,不需要二次过滤,修改查询条件即可:

if(!Strings.isNullOrEmpty(param.getAccountNumber())){
    // 直接匹配逗号分隔的账号,不需要like和后续二次过滤
    listWhere.add(builder.function("find_in_set", Integer.class, 
        builder.literal(param.getAccountNumber()), root.get("accountNumber")
    ).greaterThan(0));
}

内容的提问来源于stack exchange,提问作者hirarqi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 09:45:09