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

Hibernate 6.4 Criteria查询空指针异常问题求助

Hibernate 5.3.28升级至6.4.4后Criteria查询equal条件空指针异常解决

问题场景

将Hibernate从5.3.28版本升级至6.4.4版本后,原有正常运行的DAO方法在执行Criteria查询的equal条件时抛出空指针异常。

触发异常的DAO方法

public AuditAction findAction(Long organizationId, String actionClass, String actionName) throws Exception {
        CriteriaBuilder builder = getCriteriaBuilder();
        CriteriaQuery<AuditAction> criteria = builder.createQuery(AuditAction.class);
        Root<AuditAction> root = criteria.from(AuditAction.class);

        Predicate filter = builder.equal(root.get(AuditAction_.organization), organizationId);
        filter = builder.and(filter, builder.equal(root.get(AuditAction_.actionClassName), actionClass));
        filter = builder.and(filter, builder.equal(root.get(AuditAction_.actionName), actionName));
        criteria.where(filter);

        TypedQuery<AuditAction> q = createQuery(criteria);
        List<AuditAction> results = q.getResultList();
        return results != null && results.size() > 0 ? results.get(0) : null;
}

报错堆栈信息

Audit error!: java.lang.NullPointerException: Cannot invoke "Object.getClass()" because "value" is null
    at org.hibernate@6.4.4.Final//org.hibernate.type.descriptor.java.spi.EntityJavaType.isInstance(EntityJavaType.java:56)
    at org.hibernate@6.4.4.Final//org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder.isInstance(SqmCriteriaNodeBuilder.java:1814)
    at org.hibernate@6.4.4.Final//org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder.valueParameter(SqmCriteriaNodeBuilder.java:1856)
    at org.hibernate@6.4.4.Final//org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder.value(SqmCriteriaNodeBuilder.java:1785)
    at org.hibernate@6.4.4.Final//org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder.equal(SqmCriteriaNodeBuilder.java:2131)
    at org.hibernate@6.4.4.Final//org.hibernate.query.sqm.internal.SqmCriteriaNodeBuilder.equal(SqmCriteriaNodeBuilder.java:192)
    at deployment.HIS.war//it.gpi.his.be.ejb.entities.audit.dao.AuditActionDao.findActiveAction(AuditActionDao.java:72)
    at deployment.HIS.war//it.gpi.his.be.ejb.sessions.AuditSessionBean.handleAuditMessage(AuditSessionBean.java:327)

问题原因

  1. 类型不匹配+null值处理逻辑变更:AuditAction_.organization是实体关联类型(对应Organization实体),但代码直接用它与Long类型的organizationId比较。Hibernate 6对类型校验更严格,且当参数为null时,会尝试调用null.getClass()判断类型匹配度,直接触发空指针异常;而Hibernate 5会隐式处理这类场景,自动将equal(x, null)转为IS NULL查询。
  2. 参数null值未显式处理:原代码未考虑参数为null的情况,直接传入builder.equal,在Hibernate 6的严格校验下触发异常。

解决方法

1. 修正实体属性比较逻辑(针对ID查询)

如果organizationId是Organization实体的ID,需明确获取实体的ID属性进行比较,同时显式处理参数null值:

public AuditAction findAction(Long organizationId, String actionClass, String actionName) throws Exception {
    CriteriaBuilder builder = getCriteriaBuilder();
    CriteriaQuery<AuditAction> criteria = builder.createQuery(AuditAction.class);
    Root<AuditAction> root = criteria.from(AuditAction.class);

    Predicate filter = null;
    // 处理organization条件:明确关联ID字段,null时用isNull
    if (organizationId != null) {
        filter = builder.equal(root.get(AuditAction_.organization).get(Organization_.id), organizationId);
    } else {
        filter = builder.isNull(root.get(AuditAction_.organization));
    }
    // 处理actionClass条件
    if (actionClass != null) {
        filter = builder.and(filter, builder.equal(root.get(AuditAction_.actionClassName), actionClass));
    } else {
        filter = builder.and(filter, builder.isNull(root.get(AuditAction_.actionClassName)));
    }
    // 处理actionName条件
    if (actionName != null) {
        filter = builder.and(filter, builder.equal(root.get(AuditAction_.actionName), actionName));
    } else {
        filter = builder.and(filter, builder.isNull(root.get(AuditAction_.actionName)));
    }
    
    criteria.where(filter);

    TypedQuery<AuditAction> q = createQuery(criteria);
    List<AuditAction> results = q.getResultList();
    return results != null && !results.isEmpty() ? results.get(0) : null;
}

2. 统一null值处理规范

所有可能为null的查询参数,均需显式判断:

  • 参数非null时,使用builder.equal做等值匹配
  • 参数为null时,使用builder.isNull做空值匹配

3. 校验元模型正确性

如果AuditAction类中organization字段本身存储的是Long类型ID(而非实体对象),说明元模型生成错误,需重新生成元模型,确保AuditAction_.organization为Path<Long>类型,避免类型不匹配问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 09:39:53