问题
What is the correct syntax (JPA, Spring Data, or SpEL) to convert this query into a Spring Data Repository nativeQuery
?
SELECT *
FROM mytable
WHERE f_jsonb_arr_lower(myjsonb -> 'myArray', 'subItem', 'email')
@> '"foo@foo.com"';
I want to use an input parameter instead of hard-coding "foo@foo.com"
.
My model: Postgres myTable
with a JSONB column myJsonb
:
{
"myArray": [
{
"subItem": {
"email": "bar@bar.com"
}
},
{
"subItem": {
"email": "foo@foo.com"
}
}
]
}
Index described here.
The hard-coded version works:
@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);
But trying to leverage the lowercaseEmailAddress
parameter in a Spring Data repository nativeQuery does not work:
@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);
In my Postgres query logging, I can see that the lowercaseEmailAddress
parameter is never set:
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:
Found the answer:
1) Pass only a double-quoted String
to the spring data repository method:
String emailAddressWithDoubleQuotes = String.format("\"%s\"",emailAddress);
result = repository.findAllByEmailPageable(emailAddressWithDoubleQuotes, pageRequest).getContent();
2) The Spring Repository @Query
needs to have the SpEL expression in parenthesis and be casted to 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);
来源:https://stackoverflow.com/questions/47877601/spring-data-jpa-jsonb-paramaterization