Я пытаюсь использовать динамические имена и значения столбцов в запросе в Spring Data JPA.
interface CustomFooRepository {
fun findByValueIgnoreCase(query: String, type: RequestType): List<Foo>
}
class CustomFooRepositoryImpl(
@PersistenceContext private val entityManager: EntityManager
) : CustomFooRepository {
override fun findByValueIgnoreCase(query: String, type: RequestType): List<Foo> {
val column = when (type) {
RequestType.first_name -> "first_name"
RequestType.last_name -> "last_name"
RequestType.email -> "email"
}
val sql = """
SELECT
*,
SIMILARITY(:column, :query) AS score
FROM foo
WHERE :column iLIKE %:query%
ORDER BY score DESC NULLS LAST, :column
LIMIT 20;
"""
val constructedQuery = entityManager.createNativeQuery(sql, Foo::class.java)
constructedQuery.setParameter("column", column)
constructedQuery.setParameter("query", query)
return constructedQuery.resultList as List<Foo>
}
}
interface FooRepository : JpaRepository<Foo, Long>, CustomFooRepository
Но это дает мне
org.springframework.dao.InvalidDataAccessResourceUsageException: нет аргумента для именованного параметра ':query%'
Почему?
@TimBiegeleisen не уверен, понимаю ли я. Каким будет тогда решение?




Вы не можете объединить % внутри строки запроса. Он должен быть объединен снаружи.
Лучшее решение — добавить новый параметр:
constructedQuery.setParameter("queryWildcard", "%" + query + "%")
Итак, ваш последний литерал sql будет:
val sql = """
SELECT
*,
SIMILARITY(:column, :query) AS score
FROM foo
WHERE :column iLIKE :queryWildcard
ORDER BY score DESC NULLS LAST, :column
LIMIT 20;
"""
Это устраняет ошибку, но я получаю пустой результат, который неверен.
Первоначальной и единственной проблемой, которую вы описали, была ошибка Spring с подстановочным знаком, которая теперь решена. Эта новая проблема не имеет ничего общего с проблемой почты. Теперь проблема с вашим запросом, попробуйте выполнить запрос на консоли БД, проверьте функцию сходства и т. д. Но теперь вы знаете, как вставлять подстановочные знаки в строки запроса.
Вы вполне можете объединить параметр с помощью % внутри самого запроса, вам просто нужно использовать правильный синтаксис объединения из диалекта базы данных.
WHERE :column... это фейк, нельзя связать имя столбца с помощью подготовленного оператора.