如何将 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 方言。
假设我有一个 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 方言。