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)
问题原因
- 类型不匹配+null值处理逻辑变更:
AuditAction_.organization是实体关联类型(对应Organization实体),但代码直接用它与Long类型的organizationId比较。Hibernate 6对类型校验更严格,且当参数为null时,会尝试调用null.getClass()判断类型匹配度,直接触发空指针异常;而Hibernate 5会隐式处理这类场景,自动将equal(x, null)转为IS NULL查询。 - 参数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
相关产品推荐
相关产品推荐

