Используйте динамические имена столбцов в Spring Data JPA

Я пытаюсь использовать динамические имена и значения столбцов в запросе в 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%'

Почему?

WHERE :column ... это фейк, нельзя связать имя столбца с помощью подготовленного оператора.
Tim Biegeleisen 23.07.2024 09:12

@TimBiegeleisen не уверен, понимаю ли я. Каким будет тогда решение?

four-eyes 23.07.2024 09:14
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не можете объединить % внутри строки запроса. Он должен быть объединен снаружи.

Лучшее решение — добавить новый параметр:

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

Это устраняет ошибку, но я получаю пустой результат, который неверен.

four-eyes 23.07.2024 09:21

Первоначальной и единственной проблемой, которую вы описали, была ошибка Spring с подстановочным знаком, которая теперь решена. Эта новая проблема не имеет ничего общего с проблемой почты. Теперь проблема с вашим запросом, попробуйте выполнить запрос на консоли БД, проверьте функцию сходства и т. д. Но теперь вы знаете, как вставлять подстановочные знаки в строки запроса.

Javier Martín 23.07.2024 09:33

Вы вполне можете объединить параметр с помощью % внутри самого запроса, вам просто нужно использовать правильный синтаксис объединения из диалекта базы данных.

M. Prokhorov 23.07.2024 11:10

Другие вопросы по теме