본문 바로가기
개발

[개발] Converter 설정하기 - Java

by 공덕뉸나 2024. 11. 19.

설문조사 프로젝트를 개발하면서 엔티티를 구현하고 있는데 하나의 컬럼에 여러 가지 설문 평가 요소들을 넣기 위하여 converter가 필요해 만들게 되었다.

 

Survey

@Column(columnDefinition = "mediumText COMMENT '추가 기본 정보 수집'")
@Convert(converter = StringConverter.class)
private List<String> custom;
@Column(columnDefinition = "mediumText COMMENT '평가 요소'")
@Convert(converter = ElementConverter.class)
private List<SurveyRequest> elements;

 

StringConverter를 사용한 custom 컬럼에는 평가 요소로 미리 등록되어 있는 요소들 외에 추가적으로 수집하고자 하는 내용들을 넣을 것이다.

ElementConverter를 사용한 elements 컬럼에는 enum에 미리 넣어둔 평가 요소들을 저장할 수 있도록 할 것이다.

 

StringConverter

@Converter
public class StringConverter implements AttributeConverter<List<String>, String> {
    private static final ObjectMapper mapper = new ObjectMapper()
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);

    @Override
    public String convertToDatabaseColumn(List<String> attribute) {
        try {
            return mapper.writeValueAsString(attribute);
        } catch (JsonProcessingException e) {
            throw new IllegalArgumentException(e);
        }
    }

    @Override
    public List<String> convertToEntityAttribute(String dbData) {
        try {
            return mapper.readValue(dbData, new TypeReference<List<String>>() {});
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
    }
}

 

StringConverter의 역할

1. 목적

- List<String> 데이터를 데이터베이스에 저장 가능한 JSON 문자열로 변환하고, 이를 다시 List<String> 객체로 변환하는 역할을 한다.

2. 주요 기능

- convertToDatabaseColumn

: 엔티티의 필드 데이터(List<String>)를 데이터베이스의 컬럼(JSON 문자열) 형태로 직렬화한다.

- convertToEntityAttribute

: 데이터베이스에서 가져온 JSON 문자열 데이터를 엔티티의 필드 데이터(List<String>)로 역직렬화한다.

3. 사용 사례

- JSON 데이터를 문자열로 저장할 수 있는 데이터베이스 컬럼(ex. TEXT, VARCHAR)에 리스트 형태의 문자열 데이터를 저장하거나 불러오는 데 사용된다.

- ex) ["value1", "value2", "value"]

 

ElementConverter

@Converter
public class ElementConverter implements AttributeConverter<List<SurveyRequest>, String> {
    private final ObjectMapper mapper = new ObjectMapper()
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);

    @Override
    public String convertToDatabaseColumn(List<SurveyRequest> attribute) {
        try {
            return mapper.writeValueAsString(attribute);
        } catch (JsonProcessingException e) {
            throw new IllegalArgumentException(e);
        }
    }

    @Override
    public List<SurveyRequest> convertToEntityAttribute(String dbData) {
        TypeReference<List<SurveyRequest>> typeReference = new TypeReference<List<SurveyRequest>>() {};
        try {
            return mapper.readValue(dbData, typeReference);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
}

 

ElementConverter의 역할

1. 목적

- List<SurveyRequest> 데이터를 데이터베이스에 저장 가능한 JSON 문자열로 변환하고, 이를 다시 List<SurveyRequest> 객체로 변환하는 역할을 한다.

2. 주요 기능

위 StringConverter와 동일하다.

3. 사용 사례

- 엔터티에서 복잡한 데이터 구조(SurveyRequest 객체 리스트)를 JSON 문자열로 저장하거나 불러오는 데 사용된다.

- SurveyRequest는 엔터티가 아니며, 데이터베이스에 바로 저장할 수 없는 객체이기 때문에 JSON 형식으로 변환하여 데이터베이스에 저장한다.

- ex) [ {"id": 1, "name: "Survey1", "completed": false}, {"id": 2, "name: "Survey2", "completed": true} ]

 

공통된 역할

1. JSON 직렬화/역직렬화

- 두 컨버터 모두 Jackson 라이브러리를 사용하여 객체 -> JSON 문자열 및 JSON 문자열 -> 객체 변환을 수행한다.

2. JPA와 데이터베이스 간 타입 변환

- JPA는 기본적으로 엔티티와 데이터베이스 간 매핑을 지원하지만, 복잡한 데이터 구조(ex. 리스트, 객체리스트)를 직접 처리하지 못한다.

- 이 컨버터를 사용하면 JSON 문자열을 활용해 복잡한 구조를 데이터베이스에 저장하고, 이를 다시 객체로 변환하여 사용할 수 있다.

3. 유연한 데이터 처리

- 복잡한 데이터 구조를 유지하면서, 데이터베이스에서 쉽게 조회 및 업데이트를 할 수 있다. 

 

다음에는 코틀린으로 이 코드를 구현해보도록 해야겠다.