使用 JPA 标准和 JsonBinaryType 调用 jsonb_contains 函数 (postgres)

Der*_*erM 5 postgresql hibernate jpa criteria-api jsonb

我有一个 JPA/Hibernate 实体,它有一个 JSONB 列(使用https://github.com/vladmihalcea/hibernate-types)用于存储字符串列表。到目前为止效果很好。

@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
Run Code Online (Sandbox Code Playgroud)
@Type(type = "jsonb")
@Column(name = "TAGS", columnDefinition = "jsonb")
private List<String> tags;
Run Code Online (Sandbox Code Playgroud)

现在我想检查字符串列表中是否包含另一个字符串。

可以通过编写本机查询并使用@>Postgres 中的运算符来完成此操作。由于其他原因(查询更复杂)我不想朝那个方向走。我当前的方法是调用jsonb_containsSpring Data 规范中的方法(因为运算符只是该函数的别名),例如jsonb_contains('["tag1", "tag2", "tag3"]','["tag1"]')。我正在努力解决的是如何正确获取第二个参数。

我最初的方法是也使用字符串列表。

    public static Specification<MyEntity> hasTag(String tag) {
        return (root, query, cb) -> {
            if (StringUtils.isEmpty(tag)) {
                return criteriaBuilder.conjunction();
            }
            Expression<Boolean> expression = criteriaBuilder.function("jsonb_contains",
                                                                      Boolean.class,
                                                                      root.get("tags"),
                                                                      criteriaBuilder.literal(List.of(tag)));
            return criteriaBuilder.isTrue(expression);
        };
    }

Run Code Online (Sandbox Code Playgroud)

这会导致以下错误。

Caused by: org.postgresql.util.PSQLException: ERROR: function jsonb_contains(jsonb, character varying) does not exist
  Hinweis: No function matches the given name and argument types. You might need to add explicit type casts.
  Position: 375
Run Code Online (Sandbox Code Playgroud)

它确实知道root.get("tags")已映射到 JSONB,但对于第二个参数,它不知道。我怎样才能做到这一点?这实际上可能吗?

and*_*erz 0

我认为原因是您将varchar作为第二个参数传递。jsonb_contains()需要两个jsonb参数。

要检查 jsonb 数组包含字符串数组中的所有/任何值,您需要使用另一个运算符:?&?|

PSQL 9.4 中它们的方法绑定是:jsonb_exists_alljsonb_exists_any相应的。

在您的 PSQL 版本中,您可以通过以下命令检查它:

select * from pg_operator where oprname = '?&'
Run Code Online (Sandbox Code Playgroud)