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

设置Query.setMaxResults()时触发NullPointerException的解决方法

问题

我用Java实现了EntityA的分页查询,代码如下:

public List<EntityA> getAllEntityAByAAndDPaginated(
        Collection<Long> a, 
        Collection<Long> d, 
        int numberOfResults, 
        int page
    ) {
            TypedQuery<EntityA> q = entityManager.createNamedQuery(EntityA.GET_BY_A_AND_D,
                    EntityA.class);
            q.setParameter(A, a);
            q.setParameter(D, d);
            q.setMaxResults((page + 1) * numberOfResults * d.size()); // 去掉这句就能正常运行!
            return a != null && !a.isEmpty() && d != null && !d.isEmpty()
                    ? q.getResultList() : new ArrayList<>();
    }

为优化查询性能,我设置了(page + 1) * numberOfResults * d.size()作为最大返回结果数,但执行时触发了NullPointerException:

java.lang.NullPointerException
at java.base/java.util.ArrayList.<init>(ArrayList.java:179)
at org.eclipse.persistence.mappings.ForeignReferenceMapping.prepareNestedJoinQueryClone(ForeignReferenceMapping.java:2455)
at org.eclipse.persistence.mappings.OneToOneMapping.valueFromRowInternalWithJoin(OneToOneMapping.java:1814)
at org.eclipse.persistence.mappings.ForeignReferenceMapping.valueFromRow(ForeignReferenceMapping.java:2177)
at org.eclipse.persistence.mappings.ForeignReferenceMapping.buildCloneFromRow(ForeignReferenceMapping.java:341)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildAttributesIntoWorkingCopyClone(ObjectBuilder.java:2007)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildWorkingCopyCloneFromRow(ObjectBuilder.java:2260)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObjectInUnitOfWork(ObjectBuilder.java:858)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:745)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:699)
at ...

异常栈显示程序尝试向结果列表添加null值,移除q.setMaxResults(...)语句后代码可正常运行,且EntityA对应的数据库中无空值,请问该如何修复此问题?

修复方案
  • 修正分页逻辑
    当前setMaxResults的计算逻辑完全错误:分页的核心是用setFirstResult指定起始位置,setMaxResults指定单页数量,不需要乘以d.size()。正确的分页写法如下:

    int firstResult = page * numberOfResults;
    q.setFirstResult(firstResult);
    q.setMaxResults(numberOfResults);
    

    原逻辑会无意义放大查询结果数,触发EclipseLink处理关联映射时的边界异常。

  • 排查关联映射配置
    异常栈指向OneToOne映射的处理,说明问题出在EntityA的关联对象加载环节:

    • 检查命名查询EntityA.GET_BY_A_AND_D是否使用左连接(LEFT JOIN)加载关联对象,若关联对象必须存在,改成内连接(INNER JOIN)可避免关联对象为null的情况;
    • 若必须保留左连接,给实体类的OneToOne映射添加optional=false配置,或确保数据库关联字段有非空约束,强制ORM加载非空关联对象。
  • 提前校验参数
    原代码中setMaxResults的调用在参数校验之前,若d为null会直接触发NPE。把参数校验逻辑前置:

    public List<EntityA> getAllEntityAByAAndDPaginated(
            Collection<Long> a, 
            Collection<Long> d, 
            int numberOfResults, 
            int page
        ) {
            if (a == null || a.isEmpty() || d == null || d.isEmpty()) {
                return new ArrayList<>();
            }
            TypedQuery<EntityA> q = entityManager.createNamedQuery(EntityA.GET_BY_A_AND_D, EntityA.class);
            q.setParameter(A, a);
            q.setParameter(D, d);
            int firstResult = page * numberOfResults;
            q.setFirstResult(firstResult);
            q.setMaxResults(numberOfResults);
            return q.getResultList();
        }
    
  • 升级EclipseLink版本
    这个NPE可能是特定版本EclipseLink的已知bug,在设置setMaxResults并处理关联映射时触发。升级到最新稳定版可修复这类兼容性问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 17:25:30