SpringBoot의 @Converter
Converter란?
영어로 직역하면 전환기가 된다.
변수의 타입을 변환하여 저장 / 출력할때 사용된다.
예를들어 java에서는 'boolean'으로 값을 저장하고 Database에서는 String타입의 'Y', 또는 'N'으로 저장하고 싶을때 @Converter 어노테이션을 사용하면된다.
예시코드
책의 상품코드는 Integer로 저장하되 (ex : 100, 200, 300), 그에따른 책의 판매상태는 String으로 저장한다. (ex : 100 = "판매종료")
1. converter 객체 생성
package com.fastcampus.jpa.bookmanager.domain.converter;
import com.fastcampus.jpa.bookmanager.repository.dto.BookStatus;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
@Converter
public class BookStatusConverter implements AttributeConverter<BookStatus, Integer> {
@Override
public Integer convertToDatabaseColumn(BookStatus attribute) {
return attribute.getCode();
}
@Override
public BookStatus convertToEntityAttribute(Integer dbData) {
return dbData != null ? new BookStatus(dbData) : null;
}
}
여기서 2개의 함수를 볼 수 있는데, 각각의 역할은 다음과 같다.
(1) convertToDatabaseColumn : database 값으로 변환 (ex : 100 -> "판매종료")
(2) convertToEntityAttribute : Entity값으려 변환 (ex : "판매종료" -> 100)
2. Book 객체에 BooKStatus 코드 추가
...
public class Book extends BaseEntity{
...
@Convert(converter = BookStatusConverter.class) // Converter랑 다르다
private BookStatus status; // 판매상태
...
}
엔티티 내부에 적용하고 싶은 필드에 @Convert 어노테이션을 붙인다.
참고로 convert를 생성할때는 @Converter 어노테이션을 사용하고, 필드에 적용할때는 @Convert를 사용한다.
3. BookStatus 클래스 생성
package com.fastcampus.jpa.bookmanager.repository.dto;
import lombok.Data;
@Data
public class BookStatus {
private int code;
private String description;
public boolean isDisplayed;
public BookStatus(int code){
this.code = code;
this.description = parseDescription(code);
}
public boolean isDisplayed(){
return code == 200;
}
private String parseDescription(int code){
switch (code){
case 100:
return "판매종료";
case 200:
return "판매중";
case 300:
return "판매보류";
default:
return "미지원";
}
}
}
4. DB에 들어가는 row
insert into book(`id`, `name`, `publisher_id`, `deleted`, `status`) values (1, 'JPA 초격차 패키지', 1, false, 100);
insert into book(`id`, `name`, `publisher_id`, `deleted`, `status`) values (2, 'Spring Security 초격차 패키지', 1, false, 200);
다른 column은 보지 말고 status 컬럼만 확인하자.
결과
Book DB에서 실제로 조회되는 row들은 다음과 같다.
Book(super=BaseEntity( ... (생략) status=BookStatus(code=100, description=판매종료, isDisplayed=false))
Book(super=BaseEntity( ... (생략) status=BookStatus(code=200, description=판매중, isDisplayed=true))
Converter 안쓰고 그냥 코드 내부에서 직접 바꿔주면 안될까?
가능하다. int, string같은 raw타입으로 데이터를 맵핑하고 서비스로직에서 해당 값들의 타입을 변환해도 지장이없다.
굳이 converter를 쓰는 이유는 코드의 가독성을 높이고자 하는 목적이 가장 크다.
요즘 공개되는 오픈소스와 상용소스는 협업을 위해 가독성 높은 코드를 제공하는 것이 트렌드가 되었다.
코드의 가독성이 좋을 수록 보다 좋은 코드가 될 수 있다는 것은 반박의 여지가 없다.