我们有一个由Jdbi(org.skife.jdbi.v2
)执行的SQL语句。对于绑定参数,我们使用Jdbi' bind
方法:
Handle handle = ...
Query<Map<String, Object>> sqlQuery = handle.createQuery(query);
sqlQuery.bind(...)
但是我们在列表中遇到问题,目前我们正在使用String.format
。所以我们的查询看起来像这样:
SELECT DISTINCT
tableOne.columnOne,
tableTwo.columnTwo,
tableTwo.columnThree
FROM tableOne
JOIN tableTwo
ON tableOne.columnOne = tableTwo.columnOne
WHERE tableTwo.columnTwo = :parameterOne
AND tableTwo.columnThree IN (%s)
%s
被String.format
取代,因此我们必须在java代码中生成一个正确的字符串。然后,在替换所有%s
之后,我们使用jdbi的bind
方法替换所有其他参数(:parameterOne
或?
)。
有没有办法用jdbi替换String.format
?有一个方法bind(String, Object)
但默认情况下它不会处理列表/数组。我发现this article解释了如何编写我们自己的工厂来绑定自定义对象,但它看起来很费劲,特别是对于应该已经支持的东西。
答案 0 :(得分:12)
article you linked也会对@BindIn
注释进行说明。这为列表提供了通用的实现。
@UseStringTemplate3StatementLocator
public class MyQuery {
@SqlQuery("select id from foo where name in (<nameList>)")
List<Integer> getIds(@BindIn("nameList") List<String> nameList);
}
请注意,您必须像<
一样逃避所有尖括号\\<
。之前有一篇关于SO的论述:How to do in-query in jDBI?
答案 1 :(得分:9)
我只是想添加一个例子,因为我最近花了相当多的时间来处理一个稍微复杂的方案:
查询:
select * from sometable where id <:id and keys in (<keys>)
什么对我有用:
@UseStringTemplate3StatementLocator
public interface someDAO {
....
....
// This is the method that uses BindIn
@Mapper(someClassMapper.class)
@SqlQuery("select something from sometable where age \\< :age and name in (<names>)")
List<someclass> someMethod (@Bind("age") long age, @BindIn("names") List<string> names);
@Mapper(someClassMapper.class)
@SqlQuery("select something from sometable where id = :id")
List<someclass> someMethod1 (@Bind("id") long id);
...
...
}
注意:我确实还要添加以下依赖项,因为我正在使用
@UseStringTemplate3StatementLocator
<dependency>
<groupId>org.antlr</groupId>
<artifactId>stringtemplate</artifactId>
<version>3.2.1</version>
</dependency>
在上面的示例中要注意的主要事项是:您只需要转义小于运算符(即&lt;)而不是&lt;&gt;围绕集合变量(名称)。
正如您所看到的,我没有使用sql.stg文件来编写查询。最初我错误地认为在使用@ UseStringTemplate3StatementLocator时,我们必须在sql.stg文件中编写查询。但是,不知怎的,我从来没有让我的sql.stg文件工作,我最终还是使用@SqlQuery恢复在DAO类中编写查询。