Динамический запрос SQL с учетом фильтров
подскажите можно ли как то создать динамический SQL запрос, что я имею ввиду? Вот у меня в клиенте есть условных 6 фильтров, которые пользователь может выбирать, а может и не выбирать, если ли способ фильтровать выводимые пользователю данные только с учетом выбранных им фильтров, при этом, не создавать кучу условий в программном коде, учитывая каждый возможный случай.
Привожу пример, если было бы два фильтра user_type и document_type. Тогда в коде я бы написал 4 условия.
- Если не выбран ни один из фильтров, то есть вывожу все данные из таблицы.
- Если выбран только определенный user_type
- Если выбран только определенный document_type
- Если выбраны оба фильтра
Ответы (2 шт):
Если у вас используется Spring Data, то можно использовать JpaSpecificationExecutor и написать свою типизированную спецификацию для поиска, или QueryDslPredicateExecutor с QueryDSL, чтобы написать предикат. См. Filtering database rows with spring-data-jpa and spring-mvc
Также можно написать SQL-запрос, в котором параметры могут пропускаться путем сравнения с null:
@Query("""
select ye from YourEntity ye where
(?1 is null or ye.user_type = ?1)
and (?2 is null or ye.document_type = ?2)
""")
List<YourEntity> findFiltered(String userType, String documentType);
Можно использовать mybatis.
Он позволяет создавать динамические SQL запросы и мапить результат в объекты (это не полноценный ORM, а продвинутый маппер). Также он поддерживает скриптовые движки шаблонов, в частности velocity.
Если использовать mybatis вместе со стандартным плагином к velocity, то запрос будет выглядеть приблизительно так:
SELECT *
FROM MyEntity
#where()
#if($_parameter.user_type)
@{user_type} = user_type
#end
#if($_parameter.document_type)
AND @{document_type} = document_type
#end
#end
При вызове метода мапера mybatis сгенерирует запрос включая части условия в зависимости от того, какие параметры заданы. Если ничего не задано, то никакого WHERE вообще не будет и вернутся все данные.