迁移到Hibernate 6与QueryDSL后.transform()方法报错的解决方法
Hibernate 6.5.3.Final + QueryDSL 5.1.0 下.transform()方法报错解决办法
问题场景
项目迁移至Hibernate 6.5.3.Final + QueryDSL 5.1.0后,调用QueryDSL的.transform()方法时触发NoSuchMethodError异常,核心错误为java.lang.NoSuchMethodError: 'java.lang.Object org.hibernate.ScrollableResults.get(int)'。
相关代码
初始化类代码
public class Test{ private final EntityPath<SomeEntity> path; private final Querydsl querydsl; public Test(EntityManager entityManager) { this.path = SimpleEntityPathResolver.INSTANCE.createPath(SomeEntity.class); querydsl = new Querydsl(entityManager, new PathBuilder<SomeEntity>(this.path.getType(), this.path.getMetadata())); } }
业务方法代码
private Page<SomeObject> findAllSomeObject(JPQLQuery<?> query, Pageable pageable) { List<SomeObject> result = query .select(someExpression) .transform(GroupBy.groupBy(id) .list(Projections.constructor(SomeObject.class, someExpression)) ); return PageableExecutionUtils.getPage(result, pageable, () -> totalCount); }
异常堆栈核心信息
2025-03-27 21:32:23 [http-nio-auto-1-exec-3] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.RuntimeException: java.lang.NoSuchMethodError: 'java.lang.Object org.hibernate.ScrollableResults.get(int)'] with root cause java.lang.NoSuchMethodError: 'java.lang.Object org.hibernate.ScrollableResults.get(int)' at com.querydsl.jpa.ScrollableResultsIterator.next(ScrollableResultsIterator.java:70) at com.querydsl.core.group.GroupByList.transform(GroupByList.java:60) at com.querydsl.core.group.GroupByList.transform(GroupByList.java:36) at com.querydsl.core.support.FetchableQueryBase.transform(FetchableQueryBase.java:55) ...(省略中间堆栈内容) at java.base/java.lang.Thread.run(Thread.java:833)
解决方案
该错误本质是Hibernate 6重构了ScrollableResults接口:原get(int)方法被移除,替换为带泛型参数的get(int, Class<T>)或无参get()方法,但QueryDSL 5.1.0的JPA模块未适配这一变更。可通过以下方式解决:
升级QueryDSL版本
QueryDSL从5.2.0版本开始正式适配Hibernate 6的API变更,直接将QueryDSL依赖升级到5.2.0及以上的稳定版本,即可解决方法调用不兼容问题。手动实现分组逻辑(临时方案)
若暂时无法升级QueryDSL,可绕过GroupBy.transform(),用Java Stream API手动实现分组:private Page<SomeObject> findAllSomeObject(JPQLQuery<?> query, Pageable pageable) { // 获取原始查询结果 List<Tuple> rawResults = query.select(id, someExpression).fetch(); // 手动分组并构造目标对象 List<SomeObject> result = rawResults.stream() .collect(Collectors.groupingBy(tuple -> tuple.get(id))) .values().stream() .map(group -> group.stream() .findFirst() .map(t -> new SomeObject(t.get(someExpression))) .orElse(null)) .filter(Objects::nonNull) .collect(Collectors.toList()); return PageableExecutionUtils.getPage(result, pageable, () -> totalCount); }注:需根据实际表达式和对象构造逻辑调整代码。
排查依赖冲突
使用mvn dependency:tree(Maven)或./gradlew dependencies(Gradle)检查项目依赖树,排除混入的低版本Hibernate或QueryDSL依赖,确保依赖版本统一。
内容的提问来源于stack exchange,提问作者Mike Sonarov
相关产品推荐
相关产品推荐

