JDBI for Java 8 LocalDate and LocalDateTime

Java 8 introduced the superior LocalDate and LocalDateTime, but JDBI does not work so nicely with them. You’ll find errors like:

org.skife.jdbi.v2.exceptions.UnableToExecuteStatementException: 
org.h2.jdbc.JdbcSQLException: Cannot parse "TIMESTAMP" constant "aced00057372000d6a6176612e74696d652e536572955d84ba1b2248b20c00007870770e05000007e0060d0c2c2c0ac9d74078"

In order to bind the parameters of a JDBI DAO for these Objects, you’ll need to implement your own Binder.

import org.skife.jdbi.v2.SQLStatement;
import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.Binder;

import java.sql.Timestamp;
import java.time.LocalDateTime;

public class LocalDateTimeBinder implements Binder<Bind, LocalDateTime> {
    @Override
    public void bind(SQLStatement<?> q, Bind bind, LocalDateTime localDateTime) {
        q.bind(bind.value(), Timestamp.valueOf(localDateTime));
    }
}

Using the Binder

And in usage, set the binder for the @Bind annotation. This example also includes how an auto-incremented ID for a table will be returned when doing an insert.

@GetGeneratedKeys
@SqlUpdate("INSERT INTO my_table (name, created_date) VALUES (:name, :createdDate)")
int create(@Bind("name") String name,
@Bind(value = "createdDate", binder = LocalDateTimeBinder.class) LocalDateTime createdDate);

JDBI Binders are easy to implement, you’ll just want to be sure you’re using java.sql.Timestamp vs java.sql.Date appropriately, hint hint the latter for LocalDate.