Spring Boot升级后Hibernate6.6.2出现TableGroup定位异常求助
原项目基于Spring Boot 2.7.5 + Hibernate 5.6.12,升级至Spring Boot 3.1.0 + Hibernate 6.6.2后,执行分页计数查询时抛出异常:
org.hibernate.sql.ast.SqlTreeCreationException: Could not locate TableGroup - model.dao.User(1057834329991800)
异常触发在JPADaoImpl.getRowCount方法的rowcount=entityManager.createQuery(countCriteria).getSingleResult()行,注释countCriteria.where(fromRestriction)代码后查询正常,且原版本无此问题。
这个问题大概率不是Hibernate的bug,而是Hibernate 6对Criteria API的SQL AST构建逻辑做了更严格的校验,尤其是TableGroup(对应数据库表的逻辑分组)的关联规则。Hibernate 5允许一些隐式的表关联或条件引用,但Hibernate 6要求条件中用到的所有实体/表必须在当前Criteria查询的Root或显式关联中存在。
可行的修复方案如下:
检查并修正
fromRestriction的条件依赖
确认fromRestriction中是否包含了引用其他未关联实体的条件,比如原列表查询中关联了其他表(如User关联Order),但count查询的Criteria只以User为Root,没有显式关联这些表,导致Hibernate 6无法找到对应的TableGroup。需要确保count查询的条件中所有路径都基于当前Root,或者在count查询中显式关联所需的实体。单独构建count查询的条件
不要直接复用列表查询的fromRestriction,而是针对count查询重新构建条件。例如:// 原错误方式:复用列表查询的fromRestriction // countCriteria.where(fromRestriction); // 正确方式:针对count查询单独构建条件 CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Long> countQuery = cb.createQuery(Long.class); Root<User> countRoot = countQuery.from(User.class); countQuery.select(cb.count(countRoot)); // 重新构建适配count查询的条件,只引用countRoot的属性或显式关联的实体 Predicate countPredicate = cb.and( cb.equal(countRoot.get("status"), 1), cb.like(countRoot.get("name"), "%test%") ); countQuery.where(countPredicate);改用JPQL计数查询替代Criteria
如果Criteria方式的兼容性问题难以排查,可以直接使用JPQL编写计数查询,避开Criteria API的变动:String jpql = "select count(u) from User u where u.status = :status and u.name like :name"; Long rowcount = entityManager.createQuery(jpql, Long.class) .setParameter("status", 1) .setParameter("name", "%test%") .getSingleResult();升级Hibernate到最新补丁版本
如果确认是Hibernate的兼容性bug(比如某些特殊条件下的TableGroup定位错误),可以尝试升级到Hibernate 6.6.x的最新补丁版本,或者直接升级到6.7.x系列,新版本通常会修复已知的SQL AST构建问题。
内容的提问来源于stack exchange,提问作者Adrian

