[JPA] JPA를 적용하며.. ( field convert 편 )

2020. 11. 30. 07:00·Develop/spring-data
반응형

오늘도 JPA를 적용한 프로젝트를 진행 중입니다. 지난글 [JPA] JPA를 적용하며.. ( insert, update 분기 편 ) 에서는 insert, update 분기를 if문 없이 처리하는 유틸리티 함수를 적용했습니다.  이번글에서는 Entity의 field를 convert하는 방법에 대해서 정리하겠습니다.

나를 닮았다고 한다....

사건 전말

Database Table 컬럼 중 동적으로 변하는 데이터가 있었습니다. 우리는 해당 컬럼을 varchar 타입으로 주고 Json 방식으로 저장하기로 하였습니다. 아래에 관련 table과 필드 ddl입니다.

create table staff
(
    id         bigint auto_increment
        primary key,
    age        int          null,
    name       varchar(255) null,
    meta_json  varchar(500) null	// json으로 저장될 필드
);

 

meta_json 필드에 저장될 데이터 예시입니다.

[{
    "meta_name": "name1",
    "meta_type": "type1"
},{
    "meta_name": "name2",
    "meta_type": "type2"
},{
    "meta_name": "name3",
    "meta_type": "type3"
}]

불편하다. 귀찮다

그럼 Java에서 meta_json 데이터를 조회할 때마다 JSON 타입을 List<Vo> 로 컨버트해서 쓰면 되겠다!  

불편하다!! 협업하는 프로젝트이기 때문에 개발자1은 HashMap으로 가져오고 개발자2는 Vo로 가져오고.. 이걸 방지하기 위해서 Vo만들어놨어요 Convert 공통 메서드 만들어놨어요 이거 쓰세요. json 필드를 만들때마다?? 이럴순 없다!!

협업에서 중요한 건 개발자들의 My way보단 공통화된 소스로 작업하는 것이 중요하다고 생각합니다. 
각자 다른 스타일로 만들면 내가 작성한 외 코드를 볼 때 새로 분석을 해야합니다. 그사람의 디자인 패턴 분석...
소스가 같은 패턴으로 작성되면 유지보수할 때에도 소스가 눈에 잘 들어올 것이고 그럼 당연히 분석도 쉬울 것입니다. 

 

해답

그래서 구글링으로 해답을 찾았습니다. @Convert를 Entity json 필드에 선언하면 끝! 사용하기도 쉽고 모든 개발자가 Entity 필드 타입만 보아도 공통되게 쓸 수 있을 것입니다.

 

적용

먼저 Json 타입의 데이터와 매핑이 가능한 Vo를 생성합니다.

@Getter
@Setter
@ToString
public class StaffMetaVo {
    private String metaName;
    private String metaType;
}

 

다음으로 디비의 데이터를 컨버터하는 클래스를 생성합니다.

@Slf4j
@Converter
public class MetaListConverter implements AttributeConverter<List<StaffMetaVo>, String> {

    @Override
    public String convertToDatabaseColumn(List<StaffMetaVo> list) {
        if(CollectionUtils.isNullOrEmpty(list)) {
            return new String();
        }

        try {
            ObjectMapper objectMapper = CommonUtils.getMapper();
            return objectMapper.writeValueAsString(list);
        } catch (JsonProcessingException e) {
            log.info("failed to parse database. data to json.");
            return new String();
        }
    }

    @Override
    public List<StaffMetaVo> convertToEntityAttribute(String dbData) {
        try {
            ObjectMapper objectMapper = CommonUtils.getMapper();
            return Arrays.asList(objectMapper.readValue(dbData, StaffMetaVo[].class));
        } catch (JsonProcessingException e) {
            log.info("failed to parse database. data to json.");
            return Collections.emptyList();
        }
    }
}
  • @Converter를 선언합니다.
  • AttributeConverter를 implements 합니다. <변환될 타입, 변환할 타입>
  • ObjectMapper를 이용하여 convert합니다.

 

마지막으로 Entity 객체에 convert 대상이 될 필드에 @Convert를 붙혀줍니다.

@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PUBLIC)
public class Staff {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String address;
    
    @Convert(converter = MetaListConverter.class)
    private List<StaffMetaVo> metaJson;

    @Builder
    public Store(Long id, String name, String address, List<StaffMetaVo> metaJson) {
        this.id = id;
        this.name = name;
        this.address = address;
        this.staff = staff;
        this.metaJson = metaJson;
    }
}

작성된 코드로 metaJson 필드 조회하면 List<StaffMetaVo> 타입으로 Java에서 사용할 수 있습니다. 반대로 Java에서 List<StaffMetaVo> 타입으로 사용하고 save하면 String 타입으로 변환되어 DB에 저장됩니다.

이로써 Entity를 사용하는 개발자들은 일관성있게 metaJson 필드를 사용하려면 List<StaffMetaVo> 타입을 사용하게 되었습니다!! 

 

p.s) "불편하고 귀찮다." 에서 끝나지않고 "개선해보자" 라는 생각으로 임하면 나도 성장하고 동료들도 성장하고 블로그를 읽는 분들도 성장할 수 있다고 생각합니다 :) 
반응형

'Develop > spring-data' 카테고리의 다른 글

[Querydsl] Querydsl 사용방법 3가지  (0) 2020.12.07
[JPA] JPA를 적용하며... mysql 함수 2번 호출되는 문제  (0) 2020.12.06
[JPA] JPA를 적용하며.. ( insert, update 분기 편 )  (1) 2020.11.27
[JPA] 프로젝트에 JPA를 적용하며.... ( save편 )  (0) 2020.11.26
Spring Data JPA, Querydsl 로깅처리. p6spy 원하는 로그만 출력하기  (0) 2020.11.16
'Develop/spring-data' 카테고리의 다른 글
  • [Querydsl] Querydsl 사용방법 3가지
  • [JPA] JPA를 적용하며... mysql 함수 2번 호출되는 문제
  • [JPA] JPA를 적용하며.. ( insert, update 분기 편 )
  • [JPA] 프로젝트에 JPA를 적용하며.... ( save편 )
에디개발자
에디개발자
------ 한발자국씩 성장하자 ------ Github: https://github.com/yongtaelim LinkedIn: https://www.linkedin.com/in/%EC%9A%A9%ED%83%9C-%EC%9E%84-622b69218/
    250x250
  • 에디개발자
    에디블로그
    에디개발자
    • 분류 전체보기 (207) N
      • Develop (51)
        • spring-data (28)
        • spring-batch (7)
        • devops (5)
        • java (5)
        • kotlin (3)
        • database (2)
      • MindControl (12)
      • TroubleShooting (16)
      • Study (76)
        • kotlin (16)
        • java (15)
        • spring (6)
        • test (4)
        • message-queue (10)
        • object (22)
      • Develop Tool (1)
      • Daily Develop (7)
      • Book (5)
      • AI (27) N
        • Claude (12) N
        • ChatGPT (6) N
        • Cursor (3) N
        • Gemini (4) N
        • 트랜드 (2)
      • 개발 트렌드 (8) N
        • 데일리 픽 (8) N
  • 인기 글

  • 태그

    Ai
    kotlin
    스터디
    AI 활용
    claude
    ChatGPT
    JPQL
    OpenAI
    ai 정보
    anthropic
    에디
    클로드
    개발자 도구
    코틀린
    java
    JPA
    엘레강트
    프로그래밍
    queryDSL
    객체지향
  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
에디개발자
[JPA] JPA를 적용하며.. ( field convert 편 )
상단으로

티스토리툴바