Hibernate 6迁移报错:SqmQualifiedJoin引用非关联SqmRoot
问题分析与解决方案
错误原因
Hibernate 6对JPQL的语义验证大幅增强,严格遵循JPQL规范:JOIN的ON子句只能引用当前连接的源实体、目标实体,或查询上下文已通过FROM/JOIN引入的实体。
你的查询中,JOIN AepBanMef ban ON (...)是紧跟在TiMefAccueil nomenMef之后的,Hibernate将其视为从nomenMef出发的关联JOIN,但ON条件里引用了mef(来自etab的JOIN链),不属于当前连接上下文,因此触发语义错误。
另外注意:JPQL标准中判断null需用is null而非= null,Hibernate 6对这一语法细节也做了严格校验。
修复方案
方案1:显式声明交叉连接,调整JOIN上下文
将原来逗号分隔的TiMefAccueil nomenMef改为CROSS JOIN TiMefAccueil nomenMef,明确这是交叉连接,让mef进入后续JOIN的查询上下文,此时AepBanMef ban的ON条件引用mef就符合规范了:
@Query("select etab " + "from #{#entityName} etab " + "JOIN Mef mef ON mef.etabUajId = etab.id " + "CROSS JOIN TiMefAccueil nomenMef " + "JOIN AepBanMef ban ON ((mef.code = ban.code and mef.mefRattachement is null) OR mef.mefRattachement = ban.code) " + "where ((substring(mef.code, 1, length(nomenMef.debutCodeMef)) = nomenMef.debutCodeMef" + " AND substring(" + " mef.code," + " 10 - length(nomenMef.finCodeMef10Car) + 1," + " length(nomenMef.finCodeMef10Car)" + ") = nomenMef.finCodeMef10Car)" + " OR (" + " substring(mef.mefRattachement, 1, length(nomenMef.debutCodeMef))" + " = nomenMef.debutCodeMef" + " AND substring(" + " mef.mefRattachement," + " 10 - length(nomenMef.finCodeMef10Car) + 1," + " length(nomenMef.finCodeMef10Car)" + ") = nomenMef.finCodeMef10Car)" + ") and mef.mefSelectionne = true and nomenMef.codeTs = :codeTs " + "and (mef.dateFermeture > current_date OR mef.dateFermeture is null)" + "and (ban.dateFermeture > current_date OR ban.dateFermeture is null)") List<EtabUaj> findEtabsByCodeTi(@Param("codeTs") String codeTs);
方案2:将JOIN条件移至WHERE子句
如果不想调整JOIN结构,可以把AepBanMef ban的关联条件从ON子句移到WHERE子句,改为三个实体的交叉连接后过滤关联关系:
@Query("select etab " + "from #{#entityName} etab " + "JOIN Mef mef ON mef.etabUajId = etab.id " + ", TiMefAccueil nomenMef " + ", AepBanMef ban " + "where ((mef.code = ban.code and mef.mefRattachement is null) OR mef.mefRattachement = ban.code) " + "and ((substring(mef.code, 1, length(nomenMef.debutCodeMef)) = nomenMef.debutCodeMef" + " AND substring(" + " mef.code," + " 10 - length(nomenMef.finCodeMef10Car) + 1," + " length(nomenMef.finCodeMef10Car)" + ") = nomenMef.finCodeMef10Car)" + " OR (" + " substring(mef.mefRattachement, 1, length(nomenMef.debutCodeMef))" + " = nomenMef.debutCodeMef" + " AND substring(" + " mef.mefRattachement," + " 10 - length(nomenMef.finCodeMef10Car) + 1," + " length(nomenMef.finCodeMef10Car)" + ") = nomenMef.finCodeMef10Car)" + ") and mef.mefSelectionne = true and nomenMef.codeTs = :codeTs " + "and (mef.dateFermeture > current_date OR mef.dateFermeture is null)" + "and (ban.dateFermeture > current_date OR ban.dateFermeture is null)") List<EtabUaj> findEtabsByCodeTi(@Param("codeTs") String codeTs);
内容的提问来源于stack exchange,提问作者Bapt_
相关产品推荐
相关产品推荐

