Skip to content

Implementing and using custom converters

Stefano Negri edited this page Dec 18, 2018 · 8 revisions

Why?

If you need to customize a datatype mapping for some reason, you can create your own Mapper implementation

Example: Java 8 LocalDate to/from java.sql.Date

Hint: if you have an updated JDBC driver you don't need to do this by hand as mapping to java.time.LocalDate should work out of the box.

Implement the org.sql2o.converters.Converter interface

    package org.example;
    ...
    public class LocalDateConverter implements Converter<LocalDate> {
        @Override
        public LocalDate convert(final Object val) throws ConverterException {
            if (val instanceof java.sql.Date) {
                return ((java.sql.Date) val).toLocalDate();
            } else {
                return null;
            }
        }

        @Override
        public Object toDatabaseParam(final LocalDate val) {
            if (val == null) {
                return null;
            } else {
                return new java.sql.Date(val.atStartOfDay().toInstant(ZoneOffset.UTC).toEpochMilli());
            }
        }
    }

Implement the org.sql2o.converters.ConverterProvider interface

    package org.example;
    
    import org.sql2o.converters.Converter;
    import org.sql2o.converters.ConvertersProvider;

    import java.util.Map;

    public class Sql2oConvertersProvider implements ConvertersProvider {
    
        @Override
        public void fill(Map<Class<?>, Converter<?>> mapToFill) {
            mapToFill.put(LocalDate.class, new LocalDateConverter());
        }
    }

Recommended mechanism for enabling the converter: use the service loader mechanism

Before Java 9

As Sql2o use the standard Java service loader mechanism, enabling a new Converter is easy:

  1. In the META-INF/services folder in your classpath (src/main/resources/META-INF/services for Maven-based projects) add an empty text file called org.sql2o.converters.ConvertersProvider
  2. Add the name of your custom converter provider class to a single line followed by a line-feed. For the example above, we would add: org.example.Sql2oConvertersProvider
  3. Inititialize Sql2o in a standard manner: new Sql2o(datasource)
  4. Your custom Converter implementation will used for converting java.sql.Date to java.time.LocalDate fields Note: you may add multiple Converters to the org.sql2o.converters.ConvertersProvider-file

Java 9 and beyond

Add a line like provides org.sql2o.converters.ConvertersProvider with org.example.Sql2oConvertersProvider; to your module-info.java

Alternative: Enable your custom converter by adding it to a NoQuirks instance at instantiation time

Example:

    final Map<Class, Converter> mappers = new HashMap<>();
    mappers.put(LocalDate.class, new LocalDateConverter());
    final Sql2o database = new Sql2o(embeddedDatabaseRule.getDataSource(),
                                     new NoQuirks(mappers));