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

如何使用JPA Criteria API查询实体类Map属性中的指定键值对

问题原因

joinMap、MapJoin这类API仅适用于映射为关联关系(如@ElementCollection、@OneToMany)、存储在独立关联表的Map属性。你的properties字段是被序列化为字符串存储在当前表的nvarchar字段,不属于关联集合,因此无法使用关联查询相关API。

解决方案

由于字段存储的是序列化后的结构化字符串(默认场景为JSON格式),可以通过CriteriaBuilder.function()调用数据库原生的结构化数据提取函数,获取指定键对应的值后做等值匹配,无需修改数据库结构。

以下为不同数据库的实现示例:

1. MySQL 场景

MySQL使用JSON_EXTRACT提取JSON键值,可搭配JSON_UNQUOTE去掉结果的引号:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Item> criteriaQuery = cb.createQuery(Item.class);
Root<Item> itemRoot = criteriaQuery.from(Item.class);
criteriaQuery.select(itemRoot);

// 配置需要匹配的键值对
String key1 = ITEM_PROPERTY_1;
String expectValue1 = "123";
String key2 = ITEM_PROPERTY_2;
String expectValue2 = "456";

// 构造第一个键值对匹配规则
Predicate pre1 = cb.equal(
    // 调用JSON_UNQUOTE去掉提取结果前后的引号
    cb.function("JSON_UNQUOTE", String.class,
        cb.function("JSON_EXTRACT", String.class,
            itemRoot.get("properties"),
            // 构造JSON路径,键名加双引号避免特殊字符报错
            cb.literal("$.\"" + key1 + "\"")
        )
    ),
    cb.literal(expectValue1)
);

// 构造第二个键值对匹配规则
Predicate pre2 = cb.equal(
    cb.function("JSON_UNQUOTE", String.class,
        cb.function("JSON_EXTRACT", String.class,
            itemRoot.get("properties"),
            cb.literal("$.\"" + key2 + "\"")
        )
    ),
    cb.literal(expectValue2)
);

criteriaQuery.where(cb.and(pre1, pre2));
Item item = em.createQuery(criteriaQuery).getSingleResult();

2. SQL Server 场景

SQL Server直接使用JSON_VALUE即可提取到无引号的键值:

Predicate pre1 = cb.equal(
    cb.function("JSON_VALUE", String.class,
        itemRoot.get("properties"),
        cb.literal("$.\"" + key1 + "\"")
    ),
    cb.literal(expectValue1)
);

注意事项

  • 若你的Map序列化格式为XML等非JSON格式,替换为对应数据库的XML提取函数即可
  • 如果需要兼容多类数据库,可以自定义JPA方言函数,将不同数据库的提取逻辑封装为统一函数名调用
  • 键名存在特殊字符时需要做好JSON路径转义,避免执行时报语法错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 23:51:02