MyBatis-Plus TypeHandler 이해와 활용

MyBatis-Plus의 TypeHandlerJava 타입과 JDBC 타입 간 변환을 담당하는 핵심 컴포넌트로, 데이터베이스 컬럼 타입과 Java 객체 속성 타입 불일치 문제를 해결하며 JSON, 열거형, 사용자 정의 객체 등 복합 타입 처리에 필수적입니다.

TypeHandler의 핵심 기능

  1. 타입 변환 브리징 SQL 실행 시 Java 객체 값을 PreparedStatement에 설정하거나, ResultSet/CallableStatement에서 값을 추출해 Java 타입으로 변환합니다.
  2. 복합 타입 지원 기본 타입(String, Integer 등)은 자동 처리되지만, JSON, 컬렉션, 사용자 정의 타입은 커스텀 핸들러 구현이 필요합니다.
  3. 유연한 설정 어노테이션 또는 XML 매핑 파일로 필드 단위 핸들러 지정이 가능합니다.

주요 적용 사례

  1. 타입 불일치 해결
  • JSON 문자열을 DB에 저장 → Java의 Map/DTO 변환
  • 콤마 구분 문자열 저장 → Java의 Set<String> 변환
  1. 특수 포맷 처리
  • 사용자 정의 날짜 형식(yyyyMMddLocalDate)
  • 민감 데이터 암호화/복호화
  1. 열거형 처리
  • DB에 열거형 name() 또는 ordinal() 값 저장 → Java 열거형 객체 변환

구현 방법

1. 내장 TypeHandler 활용

EnumOrdinalTypeHandler, EnumNameTypeHandler 등 기본 제공 핸들러 사용 예:

# application.yml 설정
mybatis-plus:
  configuration:
    default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler

2. 커스텀 TypeHandler 생성

단계 1: TypeHandler 인터페이스 구현
public class StringSetConverter implements TypeHandler<Set<String>> {
    @Override
    public void setParameter(PreparedStatement stmt, int idx, Set<String> data, JdbcType jdbcType) throws SQLException {
        String combined = String.join(";", data);
        stmt.setString(idx, combined);
    }

    @Override
    public Set<String> getResult(ResultSet rs, String col) throws SQLException {
        String raw = rs.getString(col);
        return raw == null ? null : new HashSet<>(Arrays.asList(raw.split(";")));
    }
    // ResultSet/CallableStatement 오버라이드 생략
}
단계 2: 핸들러 등록
  • 어노테이션 방식
@MappedTypes(Set.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class StringSetConverter implements TypeHandler<Set<String>> { ... }
  • XML 설정 방식
<typeHandlers>
  <typeHandler handler="com.example.StringSetConverter"/>
</typeHandlers>
단계 3: 엔티티에 핸들러 연결
  • @TableField 어노테이션
@TableName(autoResultMap = true) // 필수 활성화
public class Member {
    @TableField(typeHandler = StringSetConverter.class)
    private Set<String> tags;
}
  • XML 매핑 파일
<resultMap id="memberMap" type="com.example.Member">
    <result column="tags" property="tags" typeHandler="com.example.StringSetConverter"/>
</resultMap>

내장 핸들러 적용 예시

1. JSON 타입 변환

@TableName(autoResultMap = true)
public class Product {
    @TableField(typeHandler = JacksonTypeHandler.class)
    private Map<String, Object> specs; // JSON ↔ Map 변환
}
<!-- Jackson 의존성 추가 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.0</version>
</dependency>

2. 열거형 처리 기법

  • @EnumValue 어노테이션
public enum AccountState {
    ENABLED(10), DISABLED(20);
    @EnumValue
    private final int stateCode;
}
  • 커스텀 열거형 핸들러
public class AccountStateHandler implements TypeHandler<AccountState> {
    @Override
    public void setParameter(PreparedStatement stmt, int idx, AccountState state, JdbcType jdbcType) throws SQLException {
        stmt.setInt(idx, state.getStateCode());
    }
    // 결과 처리 메서드 생략
}

중요 주의사항

  1. autoResultMap 활성화 @TableField(typeHandler=...) 사용 시 엔티티 클래스에 @TableName(autoResultMap=true) 필수 적용
  2. 성능 고려사항 빈번한 변환 작업 시 JSON 파싱 결과 캐싱 권장
  3. 스레드 안전성 커스텀 핸들러는 상태 비저장(stateless) 방식으로 설계
  4. 버전 호환성 MyBatis 3.x와 MyBatis-Plus 3.x 간 TypeHandler 인터페이스 일치 확인

태그: MyBatis-Plus TypeHandler JDBC java 데이터 변환

7월 1일 18:02에 게시됨