java JDBI3动态创建WHERE子句

ezykj2lf  于 2023-09-29  发布在  Java
关注(0)|答案(2)|浏览(110)

我如何能创造动态

public interface ThingDAO {
   @SqlQuery("SELECT * FROM things <where>)
   List<Thing> findThingsWhere(@Define("where") String where);
}

JDBI How can I dynamically create a WHERE clause while preventing SQL Injection?
但它实际上并不适用于JDBI3

klsxnrf1

klsxnrf11#

在查询中实现动态过滤有两种主要方法:

  • 使用一个静态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为null,则things行将不会在foo_column上过滤。否则,将只返回具有指定:foo值的行。
  • 同样,如果:bar为null,则things行将不会在bar_column上过滤。否则,将只返回具有指定:bar值的行。
  • 如果两个参数都为null,则返回 all 行。

模板引擎方式

开箱即用,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>
ijnw1ujt

ijnw1ujt2#

一个有点不同但相关的用例,我发现IN子句有点奇怪,imo实现这一点的一种简单方法是使用UseStringTemplateEngine,如下所示:

public interface ThingDAO {
   @SqlQuery("SELECT * FROM things WHERE 1 = 1 "
             + "<if(someField)> AND field1 IN (<someField>) <endif> "
             + "<if(someIds)> AND some_id IN (<someIds>) <endif> ")
   @UseStringTemplateEngine
   List<Thing> findThingsWhere(
       @BindList(value = "someField", onEmpty = NULL_VALUE) List<String> values,
       @BindList(value = "someIds", onEmpty = NULL_VALUE) List<UUID> someIds);
}

相关问题