Как использовать цитату внутри LIKE jpql запроса? - PullRequest
0 голосов
/ 07 октября 2019

Итак, я пытаюсь написать собственный конструктор запросов JPQL. У меня есть конечная точка что-то вроде:

/api/library/authors/search?query=test tested

На служебном уровне этот query параметр будет преобразован в что-л, как этот запрос JPQL:

SELECT t FROM Author t WHERE t.fullName LIKE '%test tested%' 
     OR t.firstName  LIKE '%test%' 
     OR t.firstName  LIKE '%tested%' 
     OR t.secondName LIKE '%test%' 
     OR t.secondName LIKE '%tested%'

Это работает довольно хорошо для меня, но, возможно, что firstName или secondName столбцы таблицы будут содержать значения с кавычкой ', такие как O'Hara. Тогда это не сработает.

/api/library/authors/search?query=Tes O'Ha

Итак, я попытался заменить ' на двойные кавычки " в запросе на что-то вроде этого:

SELECT t FROM Author t WHERE t.fullName LIKE "%Tes O'Ha%" 
     OR t.firstName  LIKE "%Tes%" 
     OR t.firstName  LIKE "%O'Ha%" 
     OR t.secondName LIKE "%Tes%" 
     OR t.secondName LIKE "%O'Ha%"

, и я получилисключение:

org.hibernate.QueryException: unexpected char: '"'

Я также пытался заменить ' на \' и " на \". Все это не работает и выдает мне исключение ...

Я выполняю этот запрос с помощью EntityManager:

@Repository
public class SearchFor {
    @PersistenceContext
    private EntityManager entityManager;

    public List execute(String query) {
        return entityManager.createQuery(query).getResultList();
    }      
}

Как мне найти значение, содержащее одинарную кавычку '?

Ответы [ 2 ]

1 голос
/ 08 октября 2019

Я нашел решение! И ... это довольно просто. Нужно просто удвоить символ кавычки, например ''

И запрос JPQL будет выглядеть так:

SELECT t FROM Author t WHERE t.fullName LIKE '%Tes O''Ha%' 
    OR t.firstName  LIKE '%Tes%' 
    OR t.firstName  LIKE '%O''Ha%' 
    OR t.secondName LIKE '%Tes%' 
    OR t.secondName LIKE '%O''Ha%'

Вот и все!

1 голос
/ 08 октября 2019

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

Примерно так:

em.createQuery("SELECT t FROM TestEntity t WHERE t.fullName LIKE :fullName " 
                + "OR t.firstName  LIKE :firstName " 
                + "OR t.firstName  LIKE :lastName " 
                + "OR t.lastName LIKE :firstName " 
                + "OR t.lastName LIKE :lastName") 
                .setParameter("firstName", firstName) 
                .setParameter("lastName", lastName) 
                .setParameter("fullName", fullName)
                .getResultList();

Я предполагаю, что вы получите свое firstName, lastName, fullName из параметра метода в слое сервиса.

Кроме того, ваша текущая реализация делаетВаше приложение уязвимо для атак SQL / JPQL, поскольку пользователь может внедрить вредоносный код через конечную точку REST.

Подробнее о внедрении SQL: https://www.baeldung.com/sql-injection

Создание запроса с именованными и индексированными параметрами: https://www.baeldung.com/jpa-query-parameters

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...