Spring JDBC + Postgres SQL + Java 8 - conversion de/vers LocalDate

J'utilise Postgres SQL 9.2, Spring JDBC avec la version 4.0.5, et Java 8.

Java 8 introduit de nouvelles date/heure API et je voudrais l'utiliser, mais j'ai rencontré quelques difficultés.
J'ai créé une table TABLE_A:

CREATE TABLE "TABLE_A"
(
  new_date date,
  old_date date
)

Je suis à l'aide de Spring JDBC pour communiquer avec la base de données. J'ai créé classe Java qui correspond à ce tableau:

public class TableA
{
    private LocalDate newDate;
    private Date oldDate;
    //getters and setters

}

c'est mon code qui est responsable de l'insertion de nouveaux ligne:

public void create(TableA tableA)
{
    BeanPropertySqlParameterSource parameterSource = new BeanPropertySqlParameterSource(tableA);
    final String sql = "INSERT INTO public.TABLE_A (new_date,old_date) values(:newDate,:oldDate)";
    namedJdbcTemplate.update(sql,parameterSource);

}

Quand j'ai exécuté cette méthode, je suis d'exception:

org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of java.time.LocalDate. Use setObject() with an explicit Types value to specify the type to use.

j'ai donc mis à jour cretion de BeanPropertySqlParameterSource:

BeanPropertySqlParameterSource parameterSource = new BeanPropertySqlParameterSource(tableA);
parameterSource.registerSqlType("newDate", Types.DATE); 

après cette modification, j'ai pu insérer une ligne. Mais la prochaine, je voudrais extraire les lignes de la base de données. Voici ma méthode:

public List<TableA> getAll()
{
    final String sql = "select * from public.TABLE_A";
    final BeanPropertyRowMapper<TableA> rowMapper = new BeanPropertyRowMapper<TableA>(TableA.class);
    return namedJdbcTemplate.query(sql,rowMapper);
}

et bien sûr, je suis d'exception:

...
at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:474)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:511)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1119)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:902)
at org.springframework.jdbc.core.BeanPropertyRowMapper.mapRow(BeanPropertyRowMapper.java:255)
...
Caused by: java.lang.IllegalStateException: Cannot convert value of type [java.sql.Date] to required type [java.time.LocalDate] for property 'newDate': no matching editors or conversion strategy found.

J'ai donc mis à jour mon code, cette fois BeanPropertyRowMapper, j'ai ajouté le service de conversion de haricot wrapper, qui est capable d'effectuer la conversion de java.sql.Date de java.temps.LocalDate

public List<TableA> getAll()
{
    final String sql = "select * from public.TABLE_A";
    final BeanPropertyRowMapper<TableA> rowMapper = new BeanPropertyRowMapper<TableA>(TableA.class)
    {
        @Override
        protected void initBeanWrapper(BeanWrapper bw) {
            super.initBeanWrapper(bw);
           bw.setConversionService(new ConversionService() {
               @Override
               public boolean canConvert(Class<?> aClass, Class<?> aClass2) {
                   return aClass == java.sql.Date.class && aClass2 == LocalDate.class;
               }

               @Override
               public boolean canConvert(TypeDescriptor typeDescriptor, TypeDescriptor typeDescriptor2) {
                   return canConvert(typeDescriptor.getType(), typeDescriptor2.getType());
               }

               @Override
               public <T> T convert(Object o, Class<T> tClass) {
                   if(o instanceof Date && tClass == LocalDate.class)
                   {
                       return (T)((Date)o).toLocalDate();
                   }

                   return null;


       }

           @Override
           public Object convert(Object o, TypeDescriptor typeDescriptor, TypeDescriptor typeDescriptor2) {
               return convert(o,typeDescriptor2.getType());
           }
       });
    }
}   ;

return namedJdbcTemplate.query(sql,rowMapper);

et maintenant, tout fonctionne, mais c'est assez compliqué.

Est-il plus facile moyen de le réaliser?
Généralement parlant, je tiens à fonctionner sur LocalDate dans mon code Java, car il est beaucoup plus pratique, et être en mesure de persister dans la base de données. Je m'attends à ce qu'il devrait être activé par défaut.

OriginalL'auteur Adam Szecowka | 2014-08-27