Creating a custom enum mapper and using it

463 views
Skip to first unread message

Aye Thu

unread,
Feb 29, 2020, 2:35:28 PM2/29/20
to jDBI
Hi JDBI peeps,

I'm currently on jdbi 3.6.x. I've got enums that extend the following interface:

public interface HasId {
    public Integer id();
}

public enum AppState implements HasId {
    PENDING(1),
    SCHEDULED(2),
    COMPLETED(3),
    CANCELLED(4),
    RESCHEDULED(5);

    private final Integer id;

    AppState(Integer id) {
        this.id = id;
    }

    @Override
    public Integer id() {
        return id;
    }
}

This id is used to save and query enums to/from the DB (and not the ordinal value). I created a custom ColumnMapper and a custom ColumnMapperFactory to handle this but am now trying to figure out how to "register" this so that the BeanMapper will use these. How can I do this (or am I even on the right path)?

In the docs I saw EnumStrategy but it doesn't look to be extensible (or customizable) this made me more confused concerning the right direction to handle custom enums. 
Thanks!

Steven Schlansker

unread,
Mar 2, 2020, 6:23:26 PM3/2/20
to jd...@googlegroups.com


> On Feb 29, 2020, at 11:35 AM, Aye Thu <aye...@gmail.com> wrote:
>
>
> This id is used to save and query enums to/from the DB (and not the ordinal value). I created a custom ColumnMapper and a custom ColumnMapperFactory to handle this but am now trying to figure out how to "register" this so that the BeanMapper will use these. How can I do this (or am I even on the right path)?

It should be as simple as calling registerColumnMapper(new AppStateColumnMapperFactory()) on your Jdbi before opening a handle that uses it.

Keep in mind that with latest Jdbi there's a new argument preparation facility, if you write a custom ArgumentFactory as well please consider implementing ArgumentFactory.Preparable otherwise the "vanilla" enum binder might win over yours anyway.

>
> In the docs I saw EnumStrategy but it doesn't look to be extensible (or customizable) this made me more confused concerning the right direction to handle custom enums.

Right, these are just the built-in strategies. You're on the right track, writing a custom mapper for a custom type, rather than thinking of it as a special enum strategy. (An enum is just a special case of "custom type")




Aye Thu

unread,
Mar 2, 2020, 7:16:44 PM3/2/20
to jDBI
Yup, I was able to get it to work with registerColumnMapper. Thanks for the reminder related to argument binding also; right now I'm explicitly handling the parameter binding myself (instead of using the enum directly). Last question: what are the scenarios for using QualifiedColumnMapperFactory vs the regular ColumnMapperFactory?

Here's a quick blurb for the custom MapperFactory in case someone runs into a similar scenario:

@Override
public Optional<ColumnMapper<?>> build(QualifiedType<?> givenType, ConfigRegistry config) {

return Optional.of(givenType.getType())
.map(GenericTypes::getErasedType)
.filter(c -> Enum.class.isAssignableFrom(c) && HasId.class.isAssignableFrom(c))
.map(clazz -> CustomEnumMapper.byId(clazz.asSubclass(Enum.class)));
}

Steven Schlansker

unread,
Mar 2, 2020, 7:18:44 PM3/2/20
to jd...@googlegroups.com
Qualifiers are for allowing annotations to select between different behaviors for the same type.

For example, a normal String argument will bind directly as a SQL varchar,
but if you add the @Json qualifying annotation (after installing appropriate jackson / gson module)
instead it will bind as a JSON literal string in a json column.

The feature is relatively new and does not have too many uses yet built-in.
> --
> 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.
> To view this discussion on the web visit https://groups.google.com/d/msgid/jdbi/6ee771ef-e5bb-4915-8121-fc45319119fe%40googlegroups.com.

Reply all
Reply to author
Forward
0 new messages