如何使用spring数据jpa查询jsonb列?

时间:2017-05-10 18:44:47

标签: spring postgresql jpa spring-data-jpa

我在使用postgres 9.4实例获取此原生查询时遇到问题。

我的存储库有一个方法:

 @Query(value = "SELECT t.* " +
            "FROM my_table t " +
            "WHERE t.field_1 = ?1 " +
            "AND t.field_2 = 1 " +
            "AND t.field_3 IN ?2 " +
            "AND t.jsonb_field #>> '{key,subkey}' = ?3",
            nativeQuery = true)
    List<Entity> getEntities(String field1Value,
                                   Collection<Integer> field3Values,
                                   String jsonbFieldValue);

但是日志显示了这个:

SELECT t.* FROM my_table t 
WHERE t.field_1 = ?1 
  AND t.field_2 = 1 
  AND t.field_3 IN ?2 
  AND t.jsonb_field ? '{key,subkey}' = ?3

我得到了这个例外:

  

内部异常:org.postgresql.util.PSQLException:没有值   为参数2指定。

我在方法调用之前直接记录了参数,并且它们都是提供的。

我不确定为什么#>>在日志中显示?。我是否需要逃离#>>?我是否需要格式化IN的集合?我需要逃离json路径吗?

当我直接对db执行查询时,它可以工作。例如:

SELECT *
FROM my_table t
WHERE t.field_1 = 'xxxx'
  AND t.field_2 = 1
  AND t.field_3 IN (13)
  AND t.jsonb_field #>> '{key,subkey}' = 'value'

5 个答案:

答案 0 :(得分:6)

我发现春季数据中的Specification api非常有帮助 假设我们有一个名为\\item $Dom\\left(Q\\right)\\ne {\\rm R}^{2} $ y uno de los puntos no pertenecientes al dominio es $\\left({1\\over 2} ,{1\\over 2} \right).$的实体和一个名为Product的JSON(B)类型的属性。
我假设此属性包含不同语言的产品标题。一个例子可能是:title 下面的源代码通过标题和作为参数传递的语言环境找到(或者更多,如果它不是唯一字段)产品。

{"EN":"Multicolor LED light", "GR":"Πολύχρωμο LED φώς"}

您可以找到有关使用Spring Data here的方式的另一个答案 希望有所帮助。

答案 1 :(得分:2)

也许这是一个古老的话题,但是我在这里使用spring规范按字段在jsonb中进行搜索。

如果要搜索“ LIKE”,则需要使用以下代码创建类似的析取物:

final Predicate likeSearch = cb.disjunction();

此后,假设您的对象中有一个jsonb字段,即address,而address有5个字段。要在所有这些字段中进行搜索,您需要为所有字段添加“ LIKE”表达式:

for (String field : ADDRESS_SEARCH_FIELDS) {
                likeSearch.getExpressions().add(cb.like(cb.lower(cb.function("json_extract_path_text", String.class,
                        root.get("address"), cb.literal(field))), %searchKey%));
            }

其中cb是相同的criteriaBuilder。 %searchKey%是您要在地址字段中搜索的内容。

希望这会有所帮助。

答案 2 :(得分:1)

如果由于某种原因将操作员转换为问号,则应尝试使用该功能。您可以在psql控制台中使用\doS+ #>>找到相应的函数。它告诉我们所谓的函数是jsonb_extract_path_text。这将使您的查询:

@Query(value = "SELECT t.* " +
        "FROM my_table t " +
        "WHERE t.field_1 = ?1 " +
        "AND t.field_2 = 1 " +
        "AND t.field_3 IN ?2 " +
        "AND jsonb_extract_path_text(t.jsonb_field, '{key,subkey}') = ?3",
        nativeQuery = true)

答案 3 :(得分:1)

我建议不要遵循这种方式,我不喜欢遵循通用的CRUD方式(也使用StrongLoop Loopback方式的高级自动生成的DAO方法,对于Spring Data Rest maven插件,但它目前只是实验性的)。 但是使用这个JSON,现在该做什么...我正在通过@Document注释寻找类似于Spring Data中的MongoDB JSON处理的东西,但是这还没有。但还有其他方法: - )

一般来说,它是关于实现您的JSON用户类型(UserType接口):

public class YourJSONBType implements UserType {

最后,您需要使用已实现的用户类型的规范来增强JPA类:

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

    @Column(columnDefinition = "jsonb")
    @Type(type = "JsonbType")
    private Map<String,Object> info;
}

在这里查看另一篇相关文章: Mapping postgreSQL JSON column to Hibernate value type

完整的实施示例如下:

类似,但这里有一些不同的例子: http://www.wisely.top/2017/06/27/spring-data-jpa-postgresql-jsonb/?d=1

答案 4 :(得分:0)

您还可以使用FUCT JPQL键来调用自定义函数,而不使用本机查询 像这样的东西,

@Query(value = "SELECT t FROM my_table t "
        + "WHERE t.field_1=:field_1 AND t.field_2=1 AND t.field_3 IN :field_3 "
        + "AND FUNC('jsonb_extract_path_text', 'key', 'subkey')=:value")
List<Entity> getEntities(@Param("field_1") String field_1, @Param("field_3") Collection<Integer> field_3, @Param("value") String value);