[Spring] 테이블의 컬럼 하나에 N개의 값을 넣고 싶다면?

Ariul·2022년 8월 31일
0
post-thumbnail

Troubleshooting

문제

사용할데이터 우리 프로젝트에 사용할 데이터!
게시물을 등록할 때 여러 재료(ingredientsList)와 여러 태그(tagList)를 설정할 수 있다. 그래서 게시물을 관리하는 테이블(post)에 재료 리스트가 담긴 컬럼과 태그 리스트가 담긴 컬럼이 있어야 한다!

근데 리스트를 필드로 어떻게 저장하지..?
빨간줄없애보자

해결 과정

  1. AttributeConverter 인터페이스를 상속받아 StringListConverter 클래스를 구현한다.

    ⇒ tagList와 ingredientsList가 DB에 저장될 때는 통째로 String으로 변환하고, 다시 객체로 만들 때는 String을 파싱하여 List에 담는다.

package com.inno.coogle.converter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.persistence.AttributeConverter;
import java.io.IOException;
import java.util.List;

public class StringListConverter 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);
    
    // DB 테이블에 들어갈 때 적용됨
    @Override
    public String convertToDatabaseColumn(List<String> attribute) {
        try{
            // Object to JSON in String
            return mapper.writeValueAsString(attribute);
        } catch (JsonProcessingException e) {
            throw new IllegalArgumentException();
        }

    }
    
    // DB 테이블의 데이터를 Object 에 매핑시킬 때 적용됨
    @Override
    public List<String> convertToEntityAttribute(String dbData) {
        try {
            // JSON from String to Object
            return mapper.readValue(dbData, List.class);
        } catch (IOException e) {
            throw new IllegalArgumentException();
        }
    }
  1. Post Entity에서 @Convert 어노테이션을 설정하여 사용한다.
    ⇒ @Convert: 해당 클래스가 AttributeConverter를 구현한 클래스임을 지정함.
    @Convert(converter = StringListConverter.class)
    private List<String> ingredientsList;

    @Convert(converter = StringListConverter.class)
    private List<String> tagList;

이제 원하는 대로 저장이 된다!
좋았어

회고

  • 보통 tag나 ingredient를 엔티티로 빼서 테이블끼리 매핑한다. 근데 뷰 작업하시는 분이 이렇게 요청하시기도 했고, JSON Array 구조이기 때문에 Entity에서 String 타입으로 관리하는 것보다 List으로 정의하는 것이 더 효과적일 것일 거라 생각해서 이렇게 설계했다.
  • 근데 작업을 다 하고 나니 궁금한 점이 많아진다.
    1. 만약 리스트에 스트링이 하나씩 추가되는 형태였다면 수정할 때 그 값만 바꿔치기할 수 있을 텐데, 지금 상황에서는 수정할 때마다 리스트 전체를 갈아끼워야 한다. 성능적으로 괜찮은가?
    2. 리스트 전체를 갈아끼우나, 리스트를 하나씩 돌면서 그 안에 있는 스트링을 골라서 변경하나 큰 차이 없을지도..? 오히려 전체를 갈아끼우는 게 나을지도? 근데 이건 가정이잖아 성능 비교 어떻게 해!!!!?!???!?!
    3. 객체 지향 데이터베이스에서는 제1정규형을 완화해 필드 값으로 집합, 리스트, 배열 등을 가질 수 있다고 하는데, 그럼 정규화 원칙에 위배되는 것이 아닌 건지?
    4. 리스트마다 반복적으로 들어있는 태그나 재료들이 있는데, 불필요한 메모리 사용을 막으려면 또 엔티티를 따로 만드는 게 나은 것 같고..

아이고 뭐가 성능적으로 우수한 건지 모르겠다. 어쨌든 다시 다 고쳐야 할 수도..🤔

profile
정성과 진심을 담아 흔적을 기록하자💡

0개의 댓글