Spring Boot迁移Hibernate 6后Criteria关联实体排序问题
解决Spring Boot 3/Hibernate 6关联实体Criteria排序H2语法错误的方案
以下是几个可行的解决思路:
1. 在查询投影中显式包含排序字段
H2在严格模式下要求ORDER BY中的字段必须出现在SELECT结果列表里。关联查询时,Hibernate 6默认生成的SQL可能不会将关联实体的排序字段加入投影,导致触发语法错误。
修改Criteria查询,将排序字段lbAcad加入到查询的投影中即可:
CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Serveur> query = cb.createQuery(Serveur.class); Root<Serveur> serveurRoot = query.from(Serveur.class); // 关联DvAcademie表 Join<Serveur, DvAcademie> academieJoin = serveurRoot.join("dvAcademie", JoinType.INNER); // 显式将排序字段加入投影(如果需要完整实体,可使用construct方法指定所有必要属性) query.select(cb.construct( Serveur.class, serveurRoot.get("id"), serveurRoot.get("nom"), // 加入排序字段 academieJoin.get("lbAcad") )) .orderBy(cb.asc(academieJoin.get("lbAcad"))); List<Serveur> result = entityManager.createQuery(query).getResultList();
如果使用fetch关联,同样需要确保排序字段被包含在投影中,或者改用join配合显式投影。
2. 修改H2数据库连接配置,放宽语法限制
通过调整H2的连接URL参数,关闭ORDER BY字段必须在SELECT中的检查:
spring.datasource.url=jdbc:h2:mem:yourdb;DB_CLOSE_DELAY=-1;ORDER_BY_IN_SELECT=FALSE
该参数会让H2不再强制要求排序字段出现在查询结果中,直接绕过这个语法限制。
3. 通过子查询先获取排序后的ID列表,再查询完整实体
先执行一个仅返回Serveur ID的子查询,按关联实体的lbAcad排序;再根据排序后的ID列表查询完整的Serveur实体并关联DvAcademie:
CriteriaBuilder cb = entityManager.getCriteriaBuilder(); // 第一步:获取按lbAcad排序的Serveur ID列表 CriteriaQuery<Long> idQuery = cb.createQuery(Long.class); Root<Serveur> idRoot = idQuery.from(Serveur.class); Join<Serveur, DvAcademie> idJoin = idRoot.join("dvAcademie"); idQuery.select(idRoot.get("id")).orderBy(cb.asc(idJoin.get("lbAcad"))); List<Long> sortedIds = entityManager.createQuery(idQuery).getResultList(); // 第二步:根据排序后的ID查询完整实体并关联DvAcademie CriteriaQuery<Serveur> serveurQuery = cb.createQuery(Serveur.class); Root<Serveur> serveurRoot = serveurQuery.from(Serveur.class); serveurRoot.fetch("dvAcademie"); // 关联查询DvAcademie // 用CASE WHEN保持ID列表的排序顺序 serveurQuery.where(serveurRoot.get("id").in(sortedIds)) .orderBy(cb.asc(cb.selectCase() .when(serveurRoot.get("id").in(sortedIds), cb.literal(sortedIds.indexOf(serveurRoot.get("id")))) .otherwise(cb.literal(Integer.MAX_VALUE)))); List<Serveur> result = entityManager.createQuery(serveurQuery).getResultList();
4. 检查并调整Hibernate方言与H2版本
确保使用的Hibernate方言与H2版本匹配,Hibernate 6.2.x推荐使用org.hibernate.dialect.H2Dialect而非旧版的方言;同时可以尝试升级H2到最新稳定版,部分版本已修复此类语法兼容问题。
内容的提问来源于stack exchange,提问作者BrunoLochet
相关产品推荐
相关产品推荐

