MyBatis-Plus 열거형(Enum) 매핑 메커니즘 분석 및 최적의 활용법

MyBatis-Plus의 열거형 처리 개요

MyBatis를 사용할 때 가장 번거로운 작업 중 하나는 Java의 열거형(Enum)과 데이터베이스의 컬럼 값을 매핑하는 것입니다. 기본적으로 MyBatis는 열거형의 이름(String)이나 순서(Ordinal)를 저장하지만, 실제 비즈니스 환경에서는 특정 코드값(예: 1, 10, 20)을 저장해야 하는 경우가 많습니다. MyBatis-Plus는 MybatisEnumTypeHandler를 통해 별도의 TypeHandler 작성 없이도 이를 우아하게 해결할 수 있는 메커니즘을 제공합니다.

열거형 매핑을 위한 두 가지 핵심 전략

1. IEnum 인터페이스 구현 방식 (권장)

MyBatis-Plus 3.4.0 버전부터 권장되는 방식으로, 열거형이 IEnum<T> 인터페이스를 상속받아 값을 반환하는 getValue() 메서드를 구현하는 형태입니다.

public enum UserStatus implements IEnum<Integer> {
    NORMAL(1, "정상"),
    BANNED(0, "정지"),
    DELETED(-1, "삭제");

    private final int code;
    private final String description;

    UserStatus(int code, String description) {
        this.code = code;
        this.description = description;
    }

    @Override
    public Integer getValue() {
        return this.code;
    }
}

이 방식은 제네릭을 통해 저장될 데이터 타입을 명확히 정의할 수 있어 타입 안정성이 높고 코드가 정돈된다는 장점이 있습니다.

2. @EnumValue 어노테이션 활용

인터페이스 구현이 어렵거나 기존에 작성된 열거형 코드를 유지해야 할 때 유용합니다. 데이터베이스에 저장될 필드에 @EnumValue 어노테이션을 선언하면 됩니다.

public enum RoleType {
    ADMIN(100, "관리자"),
    MANAGER(50, "매니저"),
    USER(10, "일반사용자");

    @EnumValue
    private final int roleCode;
    private final String roleName;

    RoleType(int roleCode, String roleName) {
        this.roleCode = roleCode;
        this.roleName = roleName;
    }

    public int getRoleCode() { return roleCode; }
}

엔티티 적용 및 데이터베이스 설계

정의된 열거형은 엔티티 클래스에서 일반 필드처럼 선언하여 사용합니다. MyBatis-Plus는 내부적으로 해당 필드의 타입을 감지하여 적절한 처리기를 할당합니다.

@TableName("app_user")
public class UserEntity {
    private Long id;
    private String username;
    
    // IEnum 구현체 사용
    private UserStatus status;
    
    // @EnumValue 사용
    private RoleType role;
}

데이터베이스 설계 시에는 해당 열거형의 value 또는 code 타입에 맞춰 컬럼 타입을 정의해야 합니다. 예를 들어 위 예시의 경우 statusrole 컬럼은 모두 INT 타입으로 설계하는 것이 적절합니다.

전역 설정 및 패키지 스캔

Spring Boot 환경에서는 application.yml 설정을 통해 열거형이 위치한 패키지를 지정하고 기본 TypeHandler를 등록해야 합니다.

mybatis-plus:
  # 열거형 클래스들이 위치한 패키지 경로
  type-enums-package: com.example.project.enums
  configuration:
    # 기본 열거형 핸들러 설정
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler

조건부 쿼리에서의 열거형 활용

MyBatis-Plus의 Wrapper를 사용하여 쿼리를 작성할 때, 별도의 값 변환 없이 열거형 객체를 직접 전달할 수 있습니다.

// LambdaQueryWrapper 활용 예시
List<UserEntity> activeAdmins = userMapper.selectList(
    Wrappers.<UserEntity>lambdaQuery()
        .eq(UserEntity::getStatus, UserStatus.NORMAL)
        .eq(UserEntity::getRole, RoleType.ADMIN)
);

내부적으로 MybatisEnumTypeHandlerUserStatus.NORMAL 객체에서 getValue()를 호출하거나 @EnumValue가 붙은 필드 값을 추출하여 SQL 파라미터로 바인딩합니다.

성능 최적화 및 동작 원리

MyBatis-Plus는 매번 리플렉션을 통해 열거형 정보를 분석하지 않습니다. TABLE_METHOD_OF_ENUM_TYPES와 같은 내부 ConcurrentHashMap 구조를 사용하여 열거형 클래스의 메타데이터를 캐싱합니다.

  • 초기 구동 시 또는 첫 호출 시 열거형의 구조를 분석하여 캐시에 저장합니다.
  • 이후 모든 CRUD 작업은 캐싱된 정보를 바탕으로 실행되므로 런타임 성능 저하가 거의 없습니다.
  • 대량의 데이터를 처리하는 배치 작업에서도 숫자 또는 문자열 변환 수준의 가벼운 연산만 수행됩니다.

실무 적용 시 고려사항

  1. 일관성 유지: 한 프로젝트 내에서는 IEnum 방식과 @EnumValue 방식 중 하나를 선택하여 통일감 있게 사용하는 것이 유지보수에 유리합니다.
  2. 타입 일치: 데이터베이스의 컬럼 타입과 Java 열거형에서 반환하는 값의 타입이 일치하는지 반드시 확인해야 합니다.
  3. Unknown Value 처리: 데이터베이스에 정의되지 않은 값이 들어있을 경우를 대비하여 예외 처리 전략이나 기본값 설정을 검토해야 합니다.

태그: MyBatis-Plus java Enum spring-boot Database-Mapping

7월 20일 04:00에 게시됨