【问题标题】:Spring Data JPA JSONB ParamaterizationSpring Data JPA JSONB 参数化
【发布时间】:2018-06-01 08:02:53
【问题描述】:

将此查询转换为 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 存储库 nativeQuery 中利用 lowercaseEmailAddress 参数不起作用:

@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

【问题讨论】:

    标签: postgresql spring-data spring-data-jpa jsonb spring-el


    【解决方案1】:

    找到答案:

    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);
    

    【讨论】:

      猜你喜欢
      • 2022-10-21
      • 2017-10-09
      • 1970-01-01
      • 2018-11-29
      • 2019-07-02
      • 2018-12-14
      • 2015-02-28
      • 2012-06-29
      • 1970-01-01
      相关资源
      最近更新 更多