Spring Boot: mongoDB → PostgreSQL 마이그레이션: Conversing 이슈 해결
2024. 9. 24. 19:49ㆍSpring Boot
728x90
반응형
#1. 개요
- 영업보고 기능을 Java Spring Boot - PostgreSQL 환경에서 구현 완료함.
- 기존 내부적으로 서비스하던 Node / MongoDB 환경에서 구현 된 영업보고 기능 내의 데이터를 PostgreSQL 환경으로 마이그레이션을 진행해야함.
- 데이터가 너무 많아서, API 서버 상에서 데이터가 담긴 mongoDB 를 연결하여 PostgreSQL 로 로직을 통해 마이그레이션을 구현함.
- 그 과정 속에서 Conversion 이슈가 아래와 같이 발생했고, 해결함.
#2. 문제 및 해결
Exception : org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47)
- Conversion 이슈
- mongodb 에서 넘어오는 데이터가 스키마랑 달리 안 맞는 이슈 존재.
- 데이터 훑어본 결과, string 으로 명시된 데이터가 데이터 상에는 숫자로 저장 되는 경우가 존재.
@Nullable
public static Object invokeConverter(GenericConverter converter, @Nullable Object source,
TypeDescriptor sourceType, TypeDescriptor targetType) {
try {
return converter.convert(source, sourceType, targetType);
}
catch (ConversionFailedException ex) {
throw ex;
}
catch (Throwable ex) {
throw new ConversionFailedException(sourceType, targetType, source, ex);
}
}
- 위 라이브러리 코드에서 ConversionFailedException 오류 발생
- 즉 sourceType 과 targetType 이 안 맞아서 생기는 오류
- invokeConverter 메서드는 주어진 변환기(GenericConverter)를 통해 소스 데이터를 목표 타입으로 변환하려고 시도
- GenericConverter는 일반적으로 스프링 프레임워크에서 제공하는 인터페이스로, 커스텀 변환기 로직이 여기에 구현될 수 있음
- 따라서 다 string 으로 받고, double 로 따로 전환을 해주는 것으로 변경.
- Converter 코드
@Component
public class NumberToStringConverter implements Converter<Object, String> {
@Override
public String convert(Object source) {
if (source instanceof Number) {
return String.valueOf(source); // 숫자를 문자열로 변환
}
return source.toString(); // 이미 문자열인 경우 그대로 반환
}
}
- MongoConfig 상 Converter 등록
@Bean
public MongoCustomConversions customConversions() {
return new MongoCustomConversions(List.of(new NumberToStringConverter()));
}
- string → 숫자 변환 코드
public static boolean isNumeric(String str) {
return str != null && str.matches("-?\\\\d+(\\\\.\\\\d+)?");
}
public static Double strToDouble(String strValue) {
if (!isNumeric(strValue)) {
return 0.0;
}
try {
return new BigDecimal(strValue).doubleValue(); // 정확도 유지
} catch (NumberFormatException ex) {
return 0.0;
}
}
public static BigDecimal strToBigDecimal(String strValue) {
if (!isNumeric(strValue)) {
return BigDecimal.ZERO; // null 대신 0을 반환하여 값이 사라지지 않도록 처리
}
try {
return new BigDecimal(strValue); // 직접 BigDecimal로 변환
} catch (NumberFormatException ex) {
return BigDecimal.ZERO; // 변환 실패 시 0으로 대체
}
}
- 또 하나의 오류가 발생.
- 특정 크기를 넘어가는 숫자들은 0으로 반환 됨
- 디버깅을 해보니, string 으로 변경된 큰 숫자는 8.007441165E9 이런식의 string 값 처리가 됨. 그래서 bigDecimal 로 변경하는 과정에서 Numeric 으로 인식을 못함.
- 큰 숫자들의 string 값을 isNumeric() 함수의 적용했을 때 숫자로 판단을 하지 않는 것이 원인.
- 따라서 isNumeric 메서드를 아래와 같이 고쳐줌.
public static boolean isNumeric(String str) {
return str != null && str.matches("-?\\\\d+(\\\\.\\\\d+)?([eE]-?\\\\d+)?");
}
728x90
반응형
'Spring Boot' 카테고리의 다른 글
99클럽 8일차 TIL: SpringBoot - Profile (0) | 2024.04.11 |
---|---|
99클럽 2일차 TIL: Spring Boot 에러 핸들링 (2) | 2024.04.05 |
Java Spring - 공부 여정 (0) | 2024.03.16 |
스웨거(Swagger) - @ExampleObject value 속 긴 String 분리 과정 정리 (1) | 2024.03.15 |
스웨거(Swagger) - 어노테이션 간단 정리 (0) | 2024.03.14 |