less than 1 minute read

I’ve been using JDBI recently for interacting with a database in Java and I generally like it. It lets you write explicit queries, and it is relatively simple to map results back into objects (e.g. using @BindMethods).

However, one thing that is not super straightforward is how to make it work with custom types. For example, I’ve been playing with ULIDs lately as identifiers (specifically f4b6a3/ulid-creator), and I want those stored in TEXT columns in the database. It took me a while to figure out the necessary pieces.

In short, you need both an ArgumentFactory (for custom type -> db) and a ColumnMapper (for db -> custom type). It looks like this:

Jdbi jdbi = ...

jdbi.registerArgument(
    new AbstractArgumentFactory<Ulid>(Types.VARCHAR) {
      @Override
      protected Argument build(Ulid value, ConfigRegistry config) {
        return (position, statement, ctx) -> statement.setString(position, value.toString());
      }
    });

jdbi.registerColumnMapper(
    new ColumnMapper<Ulid>() {
      @Override
      public Ulid map(ResultSet r, int columnNumber, StatementContext ctx) throws SQLException {
        return Ulid.from(r.getString(columnNumber));
      }
    });

With those two registrations in place, everything else should just work. These could even be bundled together into a JdbiPlugin, which I might do at some point.

Updated: