Spring Boot 3迁移后遇重复SQL别名[COL_SK]错误求助
Spring Boot 3.x(Hibernate 6.1.7)迁移后JPQL查询报重复别名错误的解决
问题场景
从Spring Boot 2.x迁移到3.x(搭配Hibernate 6.1.7)后,原有JPQL查询代码抛出以下错误:
org.springframework.orm.jpa.JpaSystemException: Encountered a duplicated sql alias [COL_SK] during auto-discovery of a native-sql query
关联代码如下:
实体类ID字段定义:
@Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="SEQ1") @SequenceGenerator(name="SEQ1", sequenceName="SEQ1", allocationSize=1) @Column(name = "COL_SK") private Long sk;
Service层查询实现:
@PersistenceContext private EntityManager entityManager; private static final String CCN_LIST = "select c1 FROM CCN c1 where c1.ccnCode in (:ccnCdList)"; @Override public List<CCN> findByCcnCdList(List<String> ccnCdList) { List<CCN> ccns = new ArrayList<CCN>(); if (CollectionUtils.isNotEmpty(ccnCdList)) { List<List<String>> ccnCdSubLists = ListUtils.partition(ccnCdList, 2000); Query query = entityManager.createQuery(CCN_LIST, CCN.class); for (List<String> ccnCdSubList : ccnCdSubLists) { query.setParameter("ccnCdList", ccnCdSubList); ccns.addAll(query.getResultList()); } } return ccns; }
上述代码在Spring Boot 2.x环境下可正常运行。
问题原因
Hibernate 6对Query实例的状态管理机制做了调整,复用同一个Query实例多次执行查询时,内部SQL生成逻辑会重复绑定实体字段的别名,进而触发COL_SK别名重复的冲突。而Spring Boot 2.x默认使用的Hibernate 5.x对这种复用场景兼容性更强,不会出现该问题。
解决方案
取消Query实例的复用,将Query的创建逻辑移至循环内部,每次子查询都生成新的Query对象:
修改后的Service代码:
@PersistenceContext private EntityManager entityManager; private static final String CCN_LIST = "select c1 FROM CCN c1 where c1.ccnCode in (:ccnCdList)"; @Override public List<CCN> findByCcnCdList(List<String> ccnCdList) { List<CCN> ccns = new ArrayList<CCN>(); if (CollectionUtils.isNotEmpty(ccnCdList)) { List<List<String>> ccnCdSubLists = ListUtils.partition(ccnCdList, 2000); for (List<String> ccnCdSubList : ccnCdSubLists) { // 每次循环创建新的Query实例 Query query = entityManager.createQuery(CCN_LIST, CCN.class); query.setParameter("ccnCdList", ccnCdSubList); ccns.addAll(query.getResultList()); } } return ccns; }
补充说明
若坚持要复用Query实例,可尝试在每次执行后调用query.unwrap(JpaQuery.class).clearParameters()清除参数,但这种方式可靠性不如重新创建Query实例——因为Hibernate 6的Query内部包含更多不可完全重置的元数据信息。
内容的提问来源于stack exchange,提问作者Vikram R
相关产品推荐
相关产品推荐

