Существует два основных подхода к достижению динамической фильтрации в запросах:
- Используйте статическое предложение
WHERE
, а параметр NULL
означает «нет фильтрации по этому параметру».Я рекомендую вам всегда сначала попробовать этот подход. - Используйте шаблонизатор.Это требует времени для настройки и проверки и усложняет анализ запросов из-за смешивания SQL и языков шаблонов.Используйте это, когда статическое предложение
WHERE
не работает для вашего варианта использования, или вы хотите устранить дублирование между несколькими запросами.
Статический WHERE
подход предложения:
SELECT * FROM things
WHERE (:foo IS NULL OR foo_column = :foo)
AND (:bar IS NULL or bar_column = :bar)
- Если
:foo
равно нулю, то строки things
не будут фильтроваться в foo_column
.В противном случае будут возвращены только строки с указанным значением :foo
. - Аналогично, если
:bar
равно нулю, то things
строки не будут отфильтрованы по bar_column
.В противном случае будут возвращены только строки с указанным значением :bar
. - Если оба параметра равны нулю, будут возвращены все строки.
Механизм шаблоновподхода
Из коробки Jdbi 3 предоставляет только простые шаблоны, которые заменяют, например, <where>
на ваш параметр @Define("where")
.
Этот механизм шаблонов по умолчанию может быть заменен любым, что вам нравится.Jdbi предоставляет дополнительные движки шаблонов для StringTemplate 4 и для Freemarker.
StringTemplate 4 больше не поддерживается, поэтому я просто покажу вам пример для Freemarker.
FreeMarker
Добавить зависимость:
<dependency>
<groupId>org.jdbi</groupId>
<artifactId>jdbi3-freemarker</artifactId>
</dependency>
Аннотация @UseFreemarkerEngine
может использоваться для объекта SQL, что приводит к тому, что запрос сначала отображается как шаблон Freemarker.
@UseFreemarkerSqlLocator
похоже на @UseFreemarkerEngine
, но с дополнительным бонусом загрузки SQL из файлов на пути к классам.Это позволяет выполнять рефакторинг часто используемых шаблонов SQL в повторно используемые файлы, на которые можно ссылаться с помощью директивы #include
.
<#include "/org/jdbi/v3/freemarker/util.ftl">
<#include "util2.ftl">
select name from something
where id in (<#list somethings as something>${something.id}<#sep>, </#list>)
<@groupBy field="name" />
<@orderBy field="name" />
util.ftl:
<#macro orderBy field order="ASC">
ORDER BY ${field} ${order}
</#macro>
util2.ftl:
<#macro groupBy field>
GROUP BY ${field}
</#macro>