Does JDBI support binding of enum types via annotation?
For example, assuming a DAO that included a method:
@SqlQuery("select count(*) from answer a where a.foo = :foo")
Long someSqlQuery(@Bind("foo") Foo foo);
And, foo
equal to Foo.BAR
, could I expect a query:
select count(*) from answer a where a.foo = 'BAR'
If so, is toString()
utilized to determine what is substituted?
Further, Does JDBI allow for using @Bind
with any type that extends Object
? And again, if so, is toString()
used?
Jdbi is not an ORM. There is no session cache, change tracking, "open session in view", or cajoling the library to understand your schema. Instead, Jdbi provides straightforward mapping between SQL and simple tabular data structures.
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.
It is a wrapper around a JDBC Connection object. Handle provides essential methods for transaction management, statement creation, and other operations tied to the database session.
According to the source code Enum.name()
is used, not toString()
If an object is bound, jdbi uses setObject(Object object)
of the jdbc driver you're using. In my experience with PostgreSQL for example, it successfully binds Map
s to hstore
and arrays to postgreSQL array
s because that's what PostgreSQL's jdbc driver does.
If you want to handle a specific kind of objects in a specific way, you can implement ArgumentFactory
s (for which there seems to be no documentation but an example here in Stack Overflow) or BinderFactorys (which I've just discovered now.)
To address your "arbitrary types" question, you can implement a BinderFactory
to bind to anything you want.
@BindingAnnotation(UserBinder.UserBinderFactory.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface UserBinder {
public static class UserBinderFactory implements BinderFactory {
@Override
public Binder build(Annotation annotation) {
return new Binder<UserBinder, User>() {
@Override
public void bind(SQLStatement<?> q, UserBinder bind, User arg) {
q.bind("userId", arg.getUserId());
q.bind("uuid", arg.getUuid());
q.bind("openId", arg.getOpenId());
q.bind("givenName", arg.getGivenName());
// etc.
}
};
}
}
}
This is most useful if you have complex types that you want stored in a particular way, e.g. binary data, or collections that you want turned into CSVs or only stored in separate mapping tables. Then you use your new fancy binder like so:
@SqlUpdate(
"INSERT INTO user (openId,givenName,uuid," +
// etc.
") VALUES (:openId,:givenName,:uuid" +
// etc.
")"
)
public abstract int createUser(
@UserBinder User user
);
You can also use an @BindBean
annotation, which will automatically look up fields on an object by the bind parameter name (e.g. it can map a query placeholder ":userId"
to the getUserId()
method).
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