如何使用 jpa 标准检查 postgresql jsonb 列中的现有元素?

问题描述

我有一个实体如下:

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@TypeDef(name = "JsonbType",typeClass = JsonBinaryType.class)
public class Message {
    @Id
    @GeneratedValue
    private Long id;

    private String content;

    @Column(columnDeFinition = "jsonb")
    @Type(type = "JsonbType")
    private readTimes UserTimeSet;
}

public class UserTimeSet extend HashSet<UserTime> {
}

public class UserTime implement Serializable {
     private String username;
     private Date time;
}

部分记录如下:

 id |                 read_times                 
----+--------------------------------------
  1 | [{"username": "user1","time": 12312412},{"username": "user2","time": 123}]
  2 | [{"username": "user2","time": 713}]
  3 | []
  4 | []

为了使用 Hibernate 将对象保存到列,我使用了 Hibernate Types 项目。现在我想获取记录,user1 中没有 read_times 符合 JPA 标准?响应必须是 ID 为:234 的记录。

更新: 我通过查询解决了但无法转换为 JPA 标准:

SELECT * FROM message WHERE jsonb_path_exists("read_times",'$[*] ? (@.username == "user1")')

解决方法

如果使用 EclipseLink,则支持 REGEXP,并且可以在 Postgres 上运行,

您还可以使用 SQL 函数调用 JPQL 中的任何 SQL 特定语法

Predicates 的示例如下: 谓词 inJsonNumbers = cb .function("jsonb_extract_path_text",字符串类, root.get("json"),cb.literal("数字")) .in(filter.getJsonNumbers())

Predicate inJsonNames = cb
        .function("jsonb_extract_path_text",String.class,root.get("json"),cb.literal("name"))
        .in(filter.getJsonNames())

此外,您可以为 SQLFunction 表达式编写自定义 CAST(jsonField->'key' AS float),然后在 JPQL 中使用它。

public String render(Type firstArgumentType,List args,SessionFactoryImplementor factory) throws QueryException {
    return "CAST(" + args.get(0).toString() + "->'" + args.get(1).toString() + "' AS float)";
}
,

试试这个

使用临时 AS( 从 table_Name t 中选择 t.id,jsonb_array_elements(t.read_times)->>'username' 作为用户名 )

从 table_name 中选择 id,其中 id 不在 ( 从 temp 中选择 id 哪里
用户名 ='用户 1' )

enter image description here