Как преобразовать PSQLs :: json @> :: json в jpa / jpql-предикат - PullRequest
1 голос
/ 12 апреля 2019

Скажем, у меня есть db-таблица, похожая на эту:

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

user_ids JSONB-ARRAY

Пусть запись этой таблицы будет выглядеть так:

{
     "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" в разборчивых / исполняемых Критериях гибернации, которые я затем намереваюсь использовать в операторе session.createQuery(). Проще говоря, мне нужно знать, как написать этот фрагмент PSQL (user_ids::jsonb @> '[25]'::jsonb) в виде HQL-выражения.

1 Ответ

2 голосов
/ 12 апреля 2019

К счастью, каждый оператор сравнения в 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, расширив существующий.

...