Spring Boot Entity에서 Enum 사용하기

Spring boot 프로젝트에서 사용하고 있는 Enum 핸들링 방법입니다. 만들게 많아 보이지만 새로운 Enum이 추가될 때 공통을 제외하고 Enum과 컨버터 클래스만 만들어주면 됩니다.

Enum 인터페이스

public interface ConverterEnum {
    /**
     * 코드
     */
    String getCode();

    /**
     * 코드명
     */
    String getCodeName();
}

Enum

@Getter
@RequiredArgsConstructor
public enum CompanyStatusType implements ConverterEnum {
    READY("N", "접수"),
    APPROVE("Y", "승인"),
    DENY("D", "반려"),
    TERMINATE("R", "해지"),
    NONE(null, "");

    private final String code;
    private final String codeName;
}

공통 컨버터

import javax.persistence.AttributeConverter;
import java.util.EnumSet;
import java.util.Optional;

@RequiredArgsConstructor
public abstract class AbstractTypeConverter<E extends Enum<E> & ConverterEnum> implements AttributeConverter<E, String> {
    private final Class<E> targetEnumClass;
    private final boolean nullable;

    /**
     * Entity의 Enum이 DB로 저장될때 호출되는 메서드
     */
    @Override
    public String convertToDatabaseColumn(E attribute) {
        if(nullable && attribute == null) {
            attribute = EnumSet.allOf(targetEnumClass).stream()
                    .filter(e -> e.getCode() == null)
                    .findFirst()
                    .orElseThrow(() -> new IllegalArgumentException(
                            String.format("null 값 코드가 %s enum에 존재하지 않습니다.",
                                    targetEnumClass.getName())));
        }else if(!nullable && (attribute == null || attribute.getCode() == null)) {
            throw new IllegalArgumentException(
                    String.format("%s enum converter의 nullable이 false이기 때문에 null 값으로 DB에 저장할 수 없습니다.",
                            targetEnumClass.getName()));
        }

        return attribute.getCode();
    }

    /**
     * DB에서 읽은 값을 Entity의 Enum으로 컨버트될 때 호출되는 메서드
     */
    @Override
    public E convertToEntityAttribute(String dbData) {
        if(!nullable && !StringUtils.hasText(dbData)) {
            throw new IllegalArgumentException(
                    String.format("%s enum converter의 nullable이 false이기 때문에 null 또는 empty 값을 Enum으로 변환할 수 없습니다.",
                            targetEnumClass.getName()));
        }

        return EnumSet.allOf(targetEnumClass).stream()
                .filter(e -> CommonUtil.nvl(e.getCode()).equals(CommonUtil.nvl(dbData)))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException(
                        String.format("DB에서 읽은 %s 코드값이 %s enum에 존재하지 않습니다.",
                                dbData, targetEnumClass.getName())));
    }
}

컨버터

import javax.persistence.Converter;

@Converter
public class CompanyStatusTypeConverter extends AbstractTypeConverter<CompanyStatusType> {
    public CompanyStatusTypeConverter() {
        super(CompanyStatusType.class, true); // true: nullable, false: not null
    }
}

Entity

@Entity
public class CompanyEntity extends BaseEntity implements Serializable { 
    ...
        
	@Convert(converter = CompanyStatusTypeConverter.class)
    private CompanyStatusType CompanyStatusType;
    
    ...
}

댓글남기기