Spring Data JPA JSONB参数化

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Data JPA JSONB参数化相关的知识,希望对你有一定的参考价值。

将此查询转换为Spring Data Repository nativeQuery的正确语法(JPA,Spring Data或SpEL)是什么?

SELECT *
FROM   mytable 
WHERE  f_jsonb_arr_lower(myjsonb -> 'myArray', 'subItem', 'email') 
 @> '"foo@foo.com"';

我想使用输入参数而不是硬编码"foo@foo.com"

我的模型:Postgres myTable,带有JSONB列myJsonb

{
  "myArray": [
    {
      "subItem": {
        "email": "bar@bar.com"
      }
    },
    {
      "subItem": {
        "email": "foo@foo.com"
      }
    }
  ]
}

索引描述了here

硬编码版本有效:

@Query(value = 
        "SELECT m.* " +
        " FROM mytable AS m " +
        " WHERE f_jsonb_arr_lower(myjsonb -> 'myArray' ,'subItem', 'email') " + 
        "   @> '"foo@foo.com"' " +
        " ORDER BY ?#{#pageable} ", 
        // Spring Data nativeQueries with Pageable require a separate countQuery:
        countQuery = 
        "SELECT count(m.id) " +
        " FROM mytable AS m " +
        " WHERE f_jsonb_arr_lower(myjsonb -> 'myArray' ,'subItem', 'email') " +
        " @> '"foo@foo.com"' ",
        nativeQuery = true)
Page<MyTableEntity> findAllHardcodedPageable(Pageable pageable);

但是尝试在Spring Data存储库中利用lowercaseEmailAddress参数nativeQuery不起作用:

@Query(value = 
        "SELECT m.* " +
        " FROM mytable AS m " +
        " WHERE f_jsonb_arr_lower(myjsonb -> 'myArray' ,'subItem', 'email') " + 
        "   @> '"?{lowercaseEmailAddress}"' " +
        " ORDER BY ?#{#pageable} ", 
        countQuery = 
        "SELECT count(m.id) " +
        " FROM mytable AS m " +
        " WHERE f_jsonb_arr_lower(myjsonb -> 'myArray' ,'subItem', 'email') " +
        " @> '"?{lowercaseEmailAddress}"' ",
        nativeQuery = true)
Page<MyTableEntity> findAllByEmailPageable
  (String lowercaseEmailAddress, Pageable pageable);

在我的Postgres查询日志记录中,我可以看到从未设置lowercaseEmailAddress参数:

LOG:  execute S_2: COMMIT
LOG:  execute S_3: BEGIN
LOG:  execute <unnamed>: SELECT count(m.id)  FROM mytable 
   AS m  WHERE f_jsonb_arr_lower(myjsonb -> 'myArray', 
   'subitem', 'email')  @> '"?1"' 
LOG:  execute S_11: ROLLBACK
答案

找到答案:

1)只将双引号的String传递给spring数据存储库方法:

String emailAddressWithDoubleQuotes = String.format(""%s"",emailAddress);
result = repository.findAllByEmailPageable(emailAddressWithDoubleQuotes, pageRequest).getContent();

2)Spring Repository @Query需要在括号中包含SpEL表达式并将其转换为jsonb

static final String FIND_ALL_BY_EMAIL_QUERY = " FROM mytable AS m " +
        " WHERE f_jsonb_arr_lower(metadata -> 'myArray', 'subItem', 'email') " +
        " @> ( ?#{#lowercaseEmailAddress} )\:\:jsonb";
@Query( // only use 'ORDER BY #pageableWithNativeSort' on 'value' query:
        value = "SELECT m.* " + FIND_ALL_BY_EMAIL_QUERY + " ORDER BY ?#{#pageableWithNativeSort} ",
        // Spring Data nativeQueries with Pageable require a separate 'countQuery':
        countQuery = "SELECT count(m.id) " + FIND_ALL_BY_EMAIL_QUERY,
        nativeQuery = true)
Page<OrderEntity> findAllBysubItemEmail(
        @Param("lowercaseEmailAddress") String lowercaseEmailAddress,
        @Param("pageableWithNativeSort") Pageable pageableWithNativeSort);

以上是关于Spring Data JPA JSONB参数化的主要内容,如果未能解决你的问题,请参考以下文章

如何使用spring data jpa查询jsonb列?

如何在 jsonb 列上使用 Spring JPA 进行查询?

使用带有 Spring Data 和绑定参数的 Postgres JSONB 查询失败并出现 InvalidDataAccessApiUsageException

如何根据postgres的jsonb列的where条件(无本机查询)使用jpa在spring boot中选择数据?

Spring Data JPA 忽略空参数

请教关于Spring Data JPA动态查询参数的问题