복붙노트

[SPRING] Spring JDBC + Postgres SQL + Java 8 - LocalDate에서 /로 변환

SPRING

Spring JDBC + Postgres SQL + Java 8 - LocalDate에서 /로 변환

Postgres SQL 9.2, Spring JDBC 버전 4.0.5, Java 8을 사용하고 있습니다. Java 8은 새로운 날짜 / 시간 API를 도입했으며이를 사용하고 싶지만 몇 가지 어려움이 있습니다. 내가 만든 테이블 TABLE_A :

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

데이터베이스와 통신하기 위해 Spring JDBC를 사용하고 있습니다. 이 테이블에 해당하는 Java 클래스를 만들었습니다.

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

}

이것은 새로운 행을 삽입하는 책임이 내 코드입니다 :

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);

}

이 메서드를 실행했을 때 예외가 발생했습니다.

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.

그래서 BeanPropertySqlParameterSource 생성을 업데이트했습니다.

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

그 변경 후 행을 삽입 할 수있었습니다. 그러나 다음으로 데이터베이스에서 행을 가져 오려고합니다. 내 방법은 다음과 같습니다.

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);
}

그리고 물론 나는 예외가있다.

...
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.

그래서 이번에는 BeanPropertyRowMapper라는 코드를 업데이트하여 java.sql.Date에서 java.time.LocalDate 로의 변환을 수행 할 수있는 bean 래퍼로 변환 서비스를 추가했습니다.

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);

이제는 모든 것이 작동하지만 꽤 복잡합니다. 그것을 달성하는 쉬운 방법일까요? 일반적으로 Java 코드에서 LocalDate를 사용하고 싶습니다. 훨씬 편리하고 데이터베이스에 유지할 수 있기 때문입니다. 기본적으로 활성화되어 있어야합니다.

해결법

  1. ==============================

    1.JDBC를 사용한 새로운 날짜 및 날짜 API 지원은 JEP 170 : JDBC 4.2에 정의되어 있습니다. Postgres는 JDBC와의 페이지 호환성을 다운로드합니다 4.2 새로운 기능은 Postgres 버전 9.4부터 시작됩니다. 따라서 새로운 API를 사용하여 이전 드라이버에서 일부 호환성 문제가 발생합니다.

    JDBC를 사용한 새로운 날짜 및 날짜 API 지원은 JEP 170 : JDBC 4.2에 정의되어 있습니다. Postgres는 JDBC와의 페이지 호환성을 다운로드합니다 4.2 새로운 기능은 Postgres 버전 9.4부터 시작됩니다. 따라서 새로운 API를 사용하여 이전 드라이버에서 일부 호환성 문제가 발생합니다.

    심지어 setObject (1, 새로운 java.util.Date ()); 는 Postgres (MySQL이 기쁘게 받아 들였던)와 동일한 제약 조건에 의해 거부되었습니다. LocalDate와 같은 새로운 API 뿐만이 아닙니다. 일부 동작은 구현에 따라 달라 지므로 java.sql. * 만 거의 보장됩니다 (대략 말하기).

    Spring JDBC 프레임 워크에 관해서는, 나중에 다시 후회하지 않고 동작을 재정의하는 것이 효과적이라고 생각합니다. 이미 수행 한 작업에 대해 약간 다른 접근 방식을 제안합니다.

    이렇게하면 API가 지원되면 향후 리팩토링 기능을 향상시키고 개발 중에 필요한 코드 양을 줄일 수 있습니다.

    DAO 접근법을 살펴볼 수도 있습니다.

  2. ==============================

    2.Java 8 Date and Time API (JSR-310)가 지원되지만 구현이 완료되지 않았 음을 참고하십시오. https://jdbc.postgresql.org/documentation/head/8-date-time.html quote :

    Java 8 Date and Time API (JSR-310)가 지원되지만 구현이 완료되지 않았 음을 참고하십시오. https://jdbc.postgresql.org/documentation/head/8-date-time.html quote :

    Note that ZonedDateTime, Instant and OffsetTime / TIME [ WITHOUT TIMEZONE ] are not supported.
    
  3. from https://stackoverflow.com/questions/25536969/spring-jdbc-postgres-sql-java-8-conversion-from-to-localdate by cc-by-sa and MIT license