【问题标题】:How to build JPA predicate for JSONB column?如何为 JSONB 列构建 JPA 谓词?
【发布时间】:2021-01-24 09:54:20
【问题描述】:

我在 Postgres 中有一个 JSONB 列,我想根据存储在 JSON 中的键值对过滤数据。 我目前正在使用 Spring Data JPA,我想使用 Predicates 来动态触发 SQL 查询。

我发现的一个选项是 Native Query,其语法如下:

SELECT car0_.model_name, car0_.year_of_manufacture, car0_.properties 
FROM public.car AS car0_ 
WHERE car0_.year_of_manufacture < 2010 
AND car0_.properties ->> 'country_of_manufacture'='US';

但我不希望使用原生查询,因为它违背了使用 ORM 的目的。

此外,我必须动态构建查询,而不是使用静态查询,以便用户可以根据 JSON 中的任何键值对进行搜索。

【问题讨论】:

  • 这可能是不可能的。

标签: postgresql hibernate jpa spring-data-jpa jsonb


【解决方案1】:

此答案适用于 Hibernate 5.0 直到 6.0。

首先你需要打开psql,使用\doS+ -&gt;&gt;找出运算符-&gt;&gt;对应什么函数。在这种情况下jsonb_object_field_text 使您想要的条件jsonb_object_field_text(car0_.properties, 'country_of_manufacture') = 'US'

现在您需要在 Hibernate 中注册该函数才能在 JPQL 中使用它。为此,您必须实现MetadataBuilderInitializer,假设您的包是com.mysite.util

package com.mysite.util;

import org.hibernate.boot.MetadataBuilder;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.spi.MetadataBuilderInitializer;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.type.StringType;

public class SQLFunctionContributor implements MetadataBuilderInitializer {

    @Override
    public void contribute(MetadataBuilder metadataBuilder, StandardServiceRegistry serviceRegistry) {
        metadataBuilder.applySqlFunction("jsonb_object_field_text", new StandardSQLFunction("jsonb_object_field_text", StringType.INSTANCE));
    }

}

最后一步是在资源文件夹中创建一个文本文件,路径如下:

META-INF/services/org.hibernate.boot.spi.MetadataBuilderInitializer

文件必须包含新类的限定类名:

com.mysite.util.SQLFunctionContributor

现在您可以像这样在 JPQL 中使用该函数:

SELECT c FROM Car c WHERE c.yearOfManufacture < :year AND FUNCTION('jsonb_object_field_text', c.properties, 'country_of_manufacture') = :cc

【讨论】:

  • 使用函数代替运算符的缺点是,函数不会使用运算符所在的索引
  • 如果这是真的,那么也许 PostgreSQL 团队应该考虑将其索引检测注册到底层函数,而不是操作符。然而,它是这个或本机查询。大多数问题都没有完美的解决方案。
  • 你也可以贡献一个 SQLFunction 来呈现操作符...
猜你喜欢
  • 2020-07-02
  • 2015-01-14
  • 2011-11-10
  • 1970-01-01
  • 2019-12-07
  • 2020-09-23
  • 2019-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多