Binding enum value

2,125 views
Skip to first unread message

henrik.lundgren

unread,
Mar 1, 2012, 3:38:02 AM3/1/12
to jDBI
Hi,

I just started to use jdbi and is it is really impressive and
beautifully simple!

However, I have one problem: how do I bind enum values?

If I just refer to it like this:

@SqlUpdate("update myTable set state = :state where id = :id")

A value like this is inserted:
aced00057e72003a636f6d2e756e696265742e637573746f6d65726d6967726174696f6e2e7365727665722e7061662e5061664d6967726174696f6e24537461746500000000000000001200007872000e6a6176612e6c616e672e456e756d00000000000000001200007870740007494e495449414c

Shouldn't the toString method be used if an enum is encountered?

Best regards
Henrik

Brian McCallister

unread,
Mar 1, 2012, 1:27:03 PM3/1/12
to jd...@googlegroups.com

Yes, I have replicated this, will get it fixed and released ASAP.

-Brian

>
> Best regards
> Henrik

Brian McCallister

unread,
Mar 1, 2012, 1:43:46 PM3/1/12
to jd...@googlegroups.com, Henning Schmiedehausen, Thomas Dudziak

Okay, so right now it is working "as expected" but the behavior is not
good. Unless overridden the sql object api falls through to
Statement#setObject(...) which provides vendor-specific behavior based
on whatever the vendor feels like doing. It makes sense to keep the
default behavior as setObject(), it is easy to remember, but db
vendors don't always do smart things. We have a few options:

a) detect if it is an enum and bind it as a string in ObjectArgument

b) Add an enum binder which can be registered on the sql object or
method which will detect enums and bind them appropriately.

c) Provide a @ReasonablySmartBindingBehavior type annotation (example
name) which handles all these types of special cases and is must be
explicitly used.

I am actually torn on the right approach to this and would like
feedback. I suspect Statement#setObject(...) with an enum is probably
effectively broken on all drivers, so better default behavior from
JDBI makes sense, but as drivers pick up better behavior, I don't want
to create confusion around hard to find special cases when users don't
get the behavior they expect.

What do folks think?

>
> -Brian
>
>>
>> Best regards
>> Henrik

Tatu Saloranta

unread,
Mar 1, 2012, 2:03:49 PM3/1/12
to jd...@googlegroups.com
On Thu, Mar 1, 2012 at 10:43 AM, Brian McCallister <bri...@skife.org> wrote:
> On Thu, Mar 1, 2012 at 10:27 AM, Brian McCallister <bri...@skife.org> wrote:
>> On Thu, Mar 1, 2012 at 12:38 AM, henrik.lundgren
>> <carl.henri...@gmail.com> wrote:
...

> a) detect if it is an enum and bind it as a string in ObjectArgument

I don't know which way to lean, but thought I will share one
additional aspect: enums have 'name()' and 'toString()', which may or
may not do the same thing, so there's also choice between these two.
By default I think they return the same, so using toString() may make
most sense, as it can be overridden.

I think that this choice might make most sense as long as it is
overridable: JDBC drivers do quite a bit of implicit casting anyway,
so it would seem closest to "just works" goal.

-+ Tatu +-

CemoKoc

unread,
Aug 23, 2012, 2:00:58 PM8/23/12
to jd...@googlegroups.com
Hi,

This is a really painful topic and resolving this issue would be also great. 

I feel same hesitations as you regarding breaking future jdbc drivers. But the jdbc driver vendors dont have so many choices and they will need to change default behaviour eventually. 

I agree with Tatu and for me 'toString()' is great enough. 

Thanks

1 Mart 2012 Perşembe 21:03:49 UTC+2 tarihinde tsaloranta yazdı:

Cemo

unread,
Oct 29, 2012, 6:04:06 AM10/29/12
to jd...@googlegroups.com
I had resolved this issue in a separated project but I would like to contribute to JDBI. But I need your comments before pulling. 

What I found difficult to address this issue is that it should support two way solution. I mean that java --> sql and sql --> java conversions should be consistent. However toString method suggested by Tatu is not suitable because it might not support sql --> java conversion without fromString method which is not available for enums. If someone will overwrite toString method with a different semantic will lead breaking the contract between sql --> java.  Because the only way AFAIK creating an enum by a String value is "java.lang.Enum#valueOf". So instead of using toString method, using not overwritable name method will fit better.   

Currently, I had added EnumArgument and slight changes in BeanMapper to support enums. If you think that these changes makes sense, I will be glad to send a pull request for this.

Any comment?


--
 
 

Brian McCallister

unread,
Oct 29, 2012, 10:32:43 AM10/29/12
to jd...@googlegroups.com
On Mon, Oct 29, 2012 at 4:04 AM, Cemo <cemalet...@gmail.com> wrote:
> I had resolved this issue in a separated project but I would like to
> contribute to JDBI. But I need your comments before pulling.
>
> What I found difficult to address this issue is that it should support two
> way solution. I mean that java --> sql and sql --> java conversions should
> be consistent. However toString method suggested by Tatu is not suitable
> because it might not support sql --> java conversion without fromString
> method which is not available for enums. If someone will overwrite toString
> method with a different semantic will lead breaking the contract between sql
> --> java. Because the only way AFAIK creating an enum by a String value is
> "java.lang.Enum#valueOf". So instead of using toString method, using not
> overwritable name method will fit better.

Enum#name() is, I believe, the "safe" way to get the string
representation of the enum value.

> Currently, I had added EnumArgument and slight changes in BeanMapper to
> support enums. If you think that these changes makes sense, I will be glad
> to send a pull request for this.
>
> Any comment?

I don't see how this can be correct for java -> sql in the general
case. It is not clear whether an arbitrary user wants an integer type
of some kind in the database, or a string type. Thus far when there is
no clear, correct, answer we fal back to binding it as an object and
letting the driver decide. This is frequently not what the user wants,
but is consistent in the face of no obvious "correct" answer.

I think it would be good to have a "Saner Defaults" plugin, but I want
users to opt into that, as one person's sane defaults are another
person's madness inducing set of bugs (just like easy to predict, but
usually wrong, behavior of "if there is no correct answer, bind as an
object" is a madness inducing set of bugs :-)

I'm happy to modify this in 3.0 (for which I have been waiting for
lambda, as the warts in 2.X don't seem severe enough to warrant a
backwards incompat break, yet) if someone has a better proposal. In
2.X, though, I don't want to change this behavior as various folks
happen to rely (probably by happy accident of driver happening to do
whatthey want) ont he current object binding behavior, and we won't
break backwards compat in 2.X (again, though the first case was
accidental).

-Brian
> --
>
>

Tatu Saloranta

unread,
Oct 29, 2012, 12:40:05 PM10/29/12
to jd...@googlegroups.com
On Mon, Oct 29, 2012 at 3:04 AM, Cemo <cemalet...@gmail.com> wrote:
> I had resolved this issue in a separated project but I would like to
> contribute to JDBI. But I need your comments before pulling.
>
> What I found difficult to address this issue is that it should support two
> way solution. I mean that java --> sql and sql --> java conversions should
> be consistent. However toString method suggested by Tatu is not suitable
> because it might not support sql --> java conversion without fromString
> method which is not available for enums. If someone will overwrite toString
> method with a different semantic will lead breaking the contract between sql
> --> java. Because the only way AFAIK creating an enum by a String value is
> "java.lang.Enum#valueOf". So instead of using toString method, using not
> overwritable name method will fit better.

You are thinking too much within a box here. :-)

The correct way to do this -- if one wants to use toString() -- is to
do proper mapping between results of toString() and instance, and not
to rely on Enum.valueOf(). There is obviously possibility of conflicts
(author defining two enums to return same value) to check. But
otherwise it can be made to work easily.

I do not have strong opinion whether toString() is better than name(),
but it is bit more extensible, and yet works with the default Enum
implementation.

-+ Tatu +-

Cemo

unread,
Oct 29, 2012, 2:53:03 PM10/29/12
to jd...@googlegroups.com
Fair enough. I was expecting this answer. :) I will give a try this week for this. 

Thanks

Plap

unread,
Jan 23, 2013, 5:18:40 PM1/23/13
to jd...@googlegroups.com
Hi,
I like JDBI too and I would like to partecipate to this post with 2 things:

1. the developer can't override the name() method (Compilation error "Cannot override the final method from Enum<MyEnum>")

2. the developer can't "overwrite" the valueOf(String) method (Compilation error "The enum MyEnum already defines the method valueOf(String) implicitly")

I've just made a test with the 1.6 compiler. 

Nikesh shetty

unread,
Feb 25, 2015, 6:44:28 AM2/25/15
to jd...@googlegroups.com, carl.henri...@gmail.com
Guys,
I am figuring out how to use BindBean which has enums in it.
Class Something{
//someEnum
}
Now everytime I try inserting into DB using Dropwizard framework
it's giving error
org.skife.jdbi.v2.exceptions.UnableToCreateStatementException: Exception while binding

I expected dropwizard to convert that enum into String automatically

Is something I am missing??


Any pointers or help is highly appreciated



---Nikesh

Nikesh shetty

unread,
Feb 25, 2015, 6:46:32 AM2/25/15
to jd...@googlegroups.com
Hi Brian
I am figuring out how to use BindBean which has enums in it.
Class Something{
//someEnum
}
Now everytime I try inserting into DB using Dropwizard framework
it's giving error
org.skife.jdbi.v2.exceptions.UnableToCreateStatementException: Exception while binding

I expected dropwizard to convert that enum into String automatically

Is something I am missing??


Any pointers or help is highly appreciated

Steven Schlansker

unread,
Feb 25, 2015, 3:03:17 PM2/25/15
to jd...@googlegroups.com
Please provide the full error message, or a self contained test case. The actual error is in a chained exception from the one you quoted.
> --
> You received this message because you are subscribed to the Google Groups "jDBI" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to jdbi+uns...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages