How can I execute somethings like this in jDBI ?
@SqlQuery("select id from foo where name in <list of names here>")
List<Integer> getIds(@Bind("nameList") List<String> nameList);
Table: foo(id int,name varchar)
Similar to @SelectProvider from myBatis.
Similar questions has been asked How do I create a Dynamic Sql Query at runtime using JDBI's Sql Object API?, but somehow answer is not clear to me.
Jdbi is not an ORM.
JDBI is a SQL convenience library for Java. It attempts to expose relational database access in idiomatic Java, using collections, beans, and so on, while maintaining the same level of detail as JDBC. It exposes two different style APIs, a fluent style and a sql object style.
The @BindBean annotation binds JavaBeans™ properties by name. If no value is given to the annotation the bean properties will be bound directly to their property names. If a value is given, the properties will be prefixed by the value given and a period.
This should work:
@SqlQuery("select id from foo where name in (<nameList>)") List<Integer> getIds(@BindIn("nameList") List<String> nameList);
Don't forget to annotate class containing this method with:
@UseStringTemplate3StatementLocator
annotation (beacuse under the hood JDBI uses Apache StringTemplate to do such substitutions). Also note that with this annotation, you cannot use '<' character in your SQL queries without escaping (beacause it is a special symbol used by StringTemplate).
Use @Define annotation to build dynamic queries in jDBI. Example:
@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);
With PostgreSQL, I was able to use the ANY comparison and bind the collection to an array to achieve this.
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
}
}
};
}
}
}
NB: ANY is not part of the ANSI SQL standard, so this creates a hard dependency on PostgreSQL.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With