如何在JDBI中使用IN运算符?

时间:2015-10-20 15:50:54

标签: java mysql dropwizard jdbi

我正在尝试使用Dropwizard上的MYSQL JDBI进行IN查询(不相关,我假设)。

@SqlQuery("SELECT id FROM table where field in (<list>)")
List<Integer> findSomething(@BindIn("list") List<String> someList);

根据建议here,我还用

注释了这个类
@UseStringTemplate3StatementLocator

但是当我启动应用程序时,我收到以下错误:

Exception in thread "main" java.lang.annotation.AnnotationFormatError: Invalid default: public abstract java.lang.Class org.skife.jdbi.v2.sqlobject.stringtemplate.UseStringTemplate3StatementLocator.errorListener()

有没有人对如何解决这个问题有个好主意?

2 个答案:

答案 0 :(得分:13)

我认为你使用的是StringTemplate 4。 您需要使用StringTemplate 3代替StringTemplate 4。添加此依赖项

<dependency>
    <groupId>org.antlr</groupId>
    <artifactId>stringtemplate</artifactId>
    <version>3.2.1</version>
</dependency>

答案 1 :(得分:8)

有两种方法可以实现它。

<强> 1 即可。使用UseStringTemplate3StatementLocator

此注释需要使用Group Files

中的SQL语句StringTemplate

说我有这个文件PersonExternalizedSqlDAO

// PersonExternalizedSqlDAO.java

package com.daoexp.dao;

@@ExternalizedSqlViaStringTemplate3
@RegisterMapper(PersonMapper.class)
public interface PersonExternalizedSqlDAO {
    @SqlQuery
    List<Person> getPersonByNames(@BindIn("names") List<String> names);
}

由于我们使用UseStringTemplate3StatementLocator,我们必须在同一个类路径中创建*.sql.stg文件。 {strong>例如<{1}}

中的
resources/com/daoexp/dao/PersonExternalizedSqlDAO.sql.stg

现在您应该能够毫无问题地进行查询。

<强> 2 即可。另一种方法是使用group PersonExternalizedSqlDAO; getPersonByNames(names) ::= << select * from person where name in (<names>) >> 来处理具有ArgumentFactory的JDBI的自定义数据类型(在本例中为List)。这是最优选的方法。

所以创建这个列表参数工厂

@Bind

这门课的作用是什么?

  • 接受List
  • 的实例
  • 将整数/字符串列表转换为数组并使用预准备语句
  • 进行绑定

确保将此参数factory注册到您的DBI实例。

public class ListArgumentFactory implements ArgumentFactory<List> {
    @Override
    public boolean accepts(Class<?> expectedType, Object value, StatementContext ctx) {
        return value instanceof List;
    }

    @Override
    public Argument build(Class<?> expectedType, final List value, StatementContext ctx) {
        return new Argument() {
            @Override
            public void apply(int position, PreparedStatement statement, StatementContext ctx) throws SQLException {
                String type = null;
                if(value.get(0).getClass() == String.class){
                    type = "varchar";
                } else if(value.get(0).getClass() == Integer.class){
                    // For integer and so on...
                } else {
                    // throw error.. type not handled
                }
                Array array = ctx.getConnection().createArrayOf(type, value.toArray());
                statement.setArray(position, array);
            }
        };
    }
}

现在您应该能够以更简单的方式使用final DBIFactory factory = new DBIFactory(); final DBI jdbi = factory.build(environment, configuration.getDataSourceFactory(), "h2"); jdbi.registerArgumentFactory(new ListArgumentFactory()); 进行查询(即)您必须使用List。而已。

@Bind

<强>参见:

其他信息:

@RegisterMapper(PersonMapper.class)
public interface PersonDAO {
    @SqlQuery("select * from person where name = any(:names)")
    List<Person> getPersonByNames(@Bind("names") List<String> names);
}
相关问题