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

Criteria API抛出StackOverflowException的原因排查

问题分析与解决方案

这个栈溢出问题的核心是Hibernate在处理双向一对一关联的Criteria查询时,元数据解析环节出现了无限递归调用——从异常栈可以看到,AbstractSqmAttributeJoin.getNodeJavaTypeDescriptor和SqmSingularJoin.getJavaTypeDescriptor方法一直在互相调用,直到栈内存耗尽。

为什么会触发这个问题?

你的实体类双向一对一关联配置本身是正确的(Customer作为拥有方,Cart用mappedBy维护反向关联),但当你用Criteria API从Customer作为Root来关联Cart时,Hibernate在解析这个join节点的类型信息时,因为双向引用的元数据处理逻辑出现了循环,导致无限递归。

解决方案

1. 调整Criteria查询的写法(最直接的解决方法)

换个思路,从Cart作为查询Root,关联Customer来构建查询,避开触发循环的逻辑:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Cart> query = cb.createQuery(Cart.class);
// 从Cart作为Root节点
Root<Cart> cartRoot = query.from(Cart.class);
// 关联Customer
Join<Cart, Customer> customerJoin = cartRoot.join("customer");
// 使用参数表达式绑定参数(修正了你之前的拼写错误和未使用的问题)
ParameterExpression<String> usernameParam = cb.parameter(String.class);
query.select(cartRoot)
     .where(cb.equal(customerJoin.get("username"), usernameParam));
// 执行查询
Cart cart = entityManager.createQuery(query)
                         .setParameter(usernameParam, name)
                         .getSingleResult();
return cart;

2. 修复代码中的其他小问题

  • 你定义的ParameterExpression拼写错误(strignParameter → stringParameter),而且之前没有实际使用它,建议用参数表达式绑定参数,这是Criteria API的规范用法,也能避免SQL注入风险。
  • Customer类的toString方法里拼写错误:Costumer → Customer(虽然这不是栈溢出的原因,但建议修正)。

3. 升级Hibernate版本

如果你的Hibernate版本比较旧,这种元数据解析的循环调用bug可能已经在新版本中被修复了,建议升级到最新的稳定版(比如5.6.x或6.x系列)。

内容的提问来源于stack exchange,提问作者Dolphy the Reaper

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 16:47:38