如何将 PSQL ::json @> ::json 转换为 jpa/jpql-predicate

How to convert PSQLs ::json @> ::json to a jpa/jpql-predicate

假设我有一个 db-table 看起来像这样:

CREATE TABLE myTable(
   id BIGINT, 
   date TIMESTAMP, 
   user_ids JSONB 
);

user_ids是一个JSONB-ARRAY

让这个 table 的记录看起来像这样:

{
     "id":13,
     "date":"2019-01-25 11:03:57",
     "user_ids":[25, 661, 88]
};

我需要查询 user_ids 包含 25 的所有记录。在 SQL 中,我可以使用以下 select 语句实现它:

SELECT * FROM myTable where user_ids::jsonb @> '[25]'::jsonb;

现在我需要编写一个 JPA-Predicate 来呈现 "user_ids::jsonb @> '[25]'::jsonb" 到休眠 parseable/executable 条件,然后我打算在 session.createQuery() 语句中使用它。 简单来说,我需要知道如何将 PSQL-snippet (user_ids::jsonb @> '[25]'::jsonb) 写成 HQL 表达式。

幸运的是,PostgreSQL 中的每个比较运算符都只是一个函数的别名,您可以通过在 psql 控制台中键入 \doS+ 和运算符来找到别名(尽管有些运算符被认为是此搜索中的通配符,因此它们给出的结果比预期的多。

结果如下:

postgres=# \doS+ @>
                                          List of operators
   Schema   | Name | Left arg type | Right arg type | Result type |      Function       | Description 
------------+------+---------------+----------------+-------------+---------------------+-------------
 pg_catalog | @>   | aclitem[]     | aclitem        | boolean     | aclcontains         | contains
 pg_catalog | @>   | anyarray      | anyarray       | boolean     | arraycontains       | contains
 pg_catalog | @>   | anyrange      | anyelement     | boolean     | range_contains_elem | contains
 pg_catalog | @>   | anyrange      | anyrange       | boolean     | range_contains      | contains
 pg_catalog | @>   | box           | box            | boolean     | box_contain         | contains
 pg_catalog | @>   | box           | point          | boolean     | box_contain_pt      | contains
 pg_catalog | @>   | circle        | circle         | boolean     | circle_contain      | contains
 pg_catalog | @>   | circle        | point          | boolean     | circle_contain_pt   | contains
 pg_catalog | @>   | jsonb         | jsonb          | boolean     | jsonb_contains      | contains
 pg_catalog | @>   | path          | point          | boolean     | path_contain_pt     | contains
 pg_catalog | @>   | polygon       | point          | boolean     | poly_contain_pt     | contains
 pg_catalog | @>   | polygon       | polygon        | boolean     | poly_contain        | contains
 pg_catalog | @>   | tsquery       | tsquery        | boolean     | tsq_mcontains       | contains
(13 rows)

你想要的是两边的jsonb参数,我们看到有那个的函数叫做jsonb_contains。所以 jsonbcolumn @> jsonbvalue 等价于 jsonb_contains(jsonbcolumn, jsonbvalue)。现在您不能在 JPQL 或 CriteriaBuilder 中使用该函数,除非您在使用 Hibernate 时通过自定义方言注册它。如果你用的是EclipseLink,我不知道那里的情况。

从这里开始,您的选择是使用本机查询,或者通过扩展现有的 Hibernate 方言来添加您自己的 Hibernate 方言。