【问题标题】:How to do in-query in jDBI?如何在 jDBI 中进行查询?
【发布时间】:2013-10-17 10:45:42
【问题描述】:

如何在 jDBI 中执行类似的操作?

@SqlQuery("select id from foo where name in <list of names here>")
List<Integer> getIds(@Bind("nameList") List<String> nameList);

表:foo(id int,name varchar)

类似于 myBatis 中的@SelectProvider。

How do I create a Dynamic Sql Query at runtime using JDBI's Sql Object API? 有人问过类似的问题,但不知怎么回答我并不清楚。

【问题讨论】:

  • 是否有任何答案解决了这个问题?我正在尝试@BindIn,但没有运气:(

标签: java sql jdbi


【解决方案1】:

这应该可行:

@SqlQuery("select id from foo where name in (<nameList>)")
List<Integer> getIds(@BindIn("nameList") List<String> nameList);

不要忘记使用以下方法注释包含此方法的类:

@UseStringTemplate3StatementLocator

注解(因为在底层 JDBI 使用 Apache StringTemplate 来做这样的替换)。另请注意,使用此注释,您不能在 SQL 查询中使用 '

【讨论】:

  • 如何在查询中转义&lt;
  • 想通了。你应该这样做\\&lt;
  • 需要像stackoverflow.com/a/33249078/2987755中提到的那样添加依赖
  • 这很酷。但是,如果我想在进行比较之前对列表中的每个项目应用lower 函数怎么办。我试过lower(name) in (lower(&lt;nameList&gt;))。这当然行不通。有什么想法吗?
  • @VikasPrasad 为什么不在执行查询之前预处理代码中的参数?
【解决方案2】:

使用@Define 注解在jDBI 中构建动态查询。 示例:

@SqlUpdate("insert into <table> (id, name) values (:id, :name)")
public void insert(@Define("table") String table, @BindBean Something s);

@SqlQuery("select id, name from <table> where id = :id")
public Something findById(@Define("table") String table, @Bind("id") Long id);

【讨论】:

  • 我假设您必须将@UseStringTemplate3StatementLocator 添加到类中以支持@Define,但是您是如何让它在@Define 之外仍然进行参数绑定(@Bind)的?
【解决方案3】:

使用 PostgreSQL,我能够使用 ANY 比较并将集合绑定到数组来实现这一点。

public interface Foo {
    @SqlQuery("SELECT id FROM foo WHERE name = ANY (:nameList)")
    List<Integer> getIds(@BindStringList("nameList") List<String> nameList);
}

@BindingAnnotation(BindStringList.BindFactory.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface BindStringList {
    String value() default "it";

    class BindFactory implements BinderFactory {
        @Override
        public Binder build(Annotation annotation) {
            return new Binder<BindStringList, Collection<String>>() {
                @Override
                public void bind(SQLStatement<?> q, BindStringList bind, Collection<String> arg) {
                    try {
                        Array array = q.getContext().getConnection().createArrayOf("varchar", arg.toArray());
                        q.bindBySqlType(bind.value(), array, Types.ARRAY);
                    } catch (SQLException e) {
                        // handle error
                    }
                }
            };
        }
    }
}

注意:ANY 不是 ANSI SQL 标准的一部分,因此这会导致对 PostgreSQL 的硬依赖。

【讨论】:

    【解决方案4】:

    如果您使用的是 JDBI 3 Fluent API,您可以使用带有属性的bindList()

    List<String> keys = new ArrayList<String>()
    keys.add("user_name");
    keys.add("street");
    
    handle.createQuery("SELECT value FROM items WHERE kind in (<listOfKinds>)")
          .bindList("listOfKinds", keys)
          .mapTo(String.class)
          .list();
    
    // Or, using the 'vararg' definition
    handle.createQuery("SELECT value FROM items WHERE kind in (<varargListOfKinds>)")
          .bindList("varargListOfKinds", "user_name", "docs", "street", "library")
          .mapTo(String.class)
          .list();
    

    注意查询字符串如何使用&lt;listOfKinds&gt; 而不是通常的:listOfKinds

    文档在这里:http://jdbi.org/#_binding_arguments

    【讨论】:

      猜你喜欢
      • 2017-02-21
      • 1970-01-01
      • 1970-01-01
      • 2021-05-27
      • 2012-01-23
      • 2011-07-28
      • 2020-05-21
      • 2016-06-03
      • 2010-10-07
      相关资源
      最近更新 更多