You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将基于Map键值LIKE查询的@Query注解转为QueryDSL适配Hibernate6

问题解决

错误原因分析

  • 第一个报错Parameter value [cro] did not match expected type [java.util.Map (n/a)]:你直接将country.localizations集合属性传入字符串模板,该字段是Map类型,和字符串查询参数类型不匹配。
  • 第二个报错Subquery returns more than 1 row:Hibernate 6 对KEY()/VALUE()函数的处理逻辑做了调整,如果直接作用在集合属性上,会自动生成隐式子查询,单个国家对应多个本地化条目时就会触发多行子查询错误。

正确实现

核心逻辑是显式给join的Map条目声明别名,所有KEY/VALUE操作都针对该别名执行,和你原@Query里的loc别名逻辑完全一致:

import com.querydsl.core.types.dsl.MapEntryPath;
import com.querydsl.core.types.dsl.Expressions;

List<Country> findByFirstChars(String name) {
    QCountry country = QCountry.country;
    // 显式声明Map.Entry类型的别名,对应原@Query中的loc
    MapEntryPath<String, String> loc = Expressions.mapEntryPath(String.class, String.class, "loc");
    String nameMatch = name.toLowerCase() + "%";
    
    return new JPAQueryFactory(entityManager)
            .selectFrom(country)
            .distinct()
            // 绑定join关联到别名loc
            .leftJoin(country.localizations, loc).fetchJoin()
            .where(
                    // 直接用别名的key方法匹配前缀,等价于KEY(loc) LIKE 'NAME%'
                    loc.key().like("NAME%"),
                    // 用别名的value方法做小写匹配,等价于LOWER(loc) LIKE LOWER(:name)
                    loc.value().toLowerCase().like(nameMatch)
            )
            .fetch();
}

补充说明

如果需要和原SQL写法完全对齐,也可以用字符串模板实现条件,只要传入的操作对象是别名loc即可,效果和上述写法一致:

BooleanExpression whereClause1 = Expressions.stringTemplate("KEY({0})", loc).like("NAME%");
BooleanExpression whereClause2 = Expressions.stringTemplate("LOWER({0})", loc.value()).like(nameMatch);

内容的提问来源于stack exchange,提问作者user1034461

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 13:30:02