微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何为JSONB列构建JPA谓词?

如何解决如何为JSONB列构建JPA谓词?

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

我发现的一个选项是本机查询,其语法可能如下:

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中的任何键值对进行搜索

解决方法

此答案适用于Hibernate 5.0到6.0。

首先,您需要打开psql并找出运算符->>与使用\doS+ ->>对应的功能。在这种情况下,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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。