Hello,
I encountered an issue when trying to use @Bind to bind an enum type argument in JDBI 2.78. Not sure if this is addressed in the newer version or not.
In my DAO interface, I have a query method that binds to a enum Type.
@SqlQuery("SELECT A FROM TABLE_A WHERE ID = :id AND TYPE = :type")
List<TableA> findTableA(@Bind("id") long id, @Bind("type") Type type);
Type is declared as a complex Enum (when I say complex, I mean the enum values are including their own methods)
public enum Type
{
Bad
{
@Override
public int getCode()
{
return 0;
}
},
Good
{
@Override
public int getCode()
{
return 1;
}
};
public abstract int getCode();
}
This enum Type is also used in a java Bean class. We also have insert/update methods in the DAO that are using @BindBean annotation to persist to database. They work fine. But when we are trying to use @Bind to bind this Type as a single value the method fails.
I debugged JDBI code and find out why this is not working. Basically, when using @Bind with an enum type, jdbi uses the actual argument object's class type to resolve to an ArgumentFactory. In this case, type.getClass(). JDBI do a test to see if it is enum type by calling Class.isEnum() method. For a complex enum type (which declare methods in enum value), the actual class type is an inner anonymous class (something like Typ$1) which is not an enum type. Thus isEnum call return false. (See
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=5020490,
https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6709903). Since the test returns false, JDBI doesn't recognize we are trying to bind an enum type, so it resolves to ObjectArgument to bind it which fails when try to set value to sql statement because it cannot resolve to the correct column type.
But when using @BindBean, jdbi uses reflection and use property getter method's return type as the type to resolve. This time the class is Type.class, and its call to isEnum return true. So this resolves to EnumArgument correctly.
It looks like to better test enum type, we will need to use reflection to find the declared type of a bind argument with @Bind annotation. Otherwise, we have to limit the use of @Bind for simple enum type only.
Should I open a bug/feature request ticket?
Thanks.