MyBatis-Plus에서 MySQL JSON 필드 매핑 처리

MySQL의 네이티브 JSON 타입 활용

MySQL 5.7.8 버전부터 JSON 데이터 타입을 기본 제공한다. 이 기능을 통해 구조화된 데이터를 관계형 테이블 내에서 유연하게 저장하고 조작할 수 있다.

테이블 정의와 데이터 삽입

JSON 컬럼은 일반 컬럼처럼 선언 가능하며, 입력 시 유효한 JSON 형식만 허용된다.

CREATE TABLE product_config (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    product_code VARCHAR(50),
    settings JSON NOT NULL
);

데이터 삽입 예시:

INSERT INTO product_config (product_code, settings)
VALUES ('P1001', '{"theme": "dark", "notifications": true, "language": "ko"}');

주요 JSON 함수 사용법

MySQL은 JSON 필드 접근 및 수정을 위한 내장 함수를 제공한다.

  • 값 추출: ->는 JSON 문자열을 반환하고, ->>는 일반 문자열로 변환하여 따옴표 없이 출력한다.
  • SELECT settings->'$.theme' FROM product_config;        -- 결과: "dark"
    SELECT settings->>'$.theme' FROM product_config;       -- 결과: dark
    
  • 필드 업데이트: JSON_SET() 함수로 기존 키 수정 또는 새 키 추가가 가능하다.
  • UPDATE product_config 
    SET settings = JSON_SET(settings, '$.language', 'en', '$.timezone', 'UTC') 
    WHERE id = 1;
    
  • 조건 쿼리: JSON 내부 값 기준으로 조회 가능.
  • SELECT * FROM product_config 
    WHERE settings->>'$.notifications' = 'true';
    

JSON vs VARCHAR 비교

항목 JSON VARCHAR
저장 형식 최적화된 바이너리 형식 일반 문자열
유효성 검사 삽입 시 자동 검증 무검증
내부 필드 접근 함수 지원 (->, JSON_EXTRACT) 문자열 함수만 사용 가능
인덱싱 가상 컬럼 + 인덱스 가능 전체 컬럼 인덱스만 가능
성능 내부 필드 접근 빠름 매번 파싱 필요

기타 JSON 함수 요약

  • JSON_INSERT(): 존재하지 않는 키만 추가
  • JSON_REPLACE(): 존재하는 키만 갱신
  • JSON_REMOVE(): 특정 경로 삭제

실제 운영에서는 가장 유연한 JSON_SET() 사용이 권장된다.

MyBatis-Plus에서 JSON 객체 매핑

Java 애플리케이션에서 MySQL의 JSON 컬럼을 객체 형태로 사용하려면 타입 핸들러(TypeHandler)가 필요하다. MyBatis-Plus는 이를 위해 자동 ResultMap 생성 기능을 제공한다.

@TableName(autoResultMap = true)의 역할

이 어노테이션 속성은 MyBatis-Plus에게 해당 엔티티에 대해 명시적인 <resultMap>을 자동 생성하도록 지시한다. 이 맵은 컬럼과 자바 필드 간의 복잡한 변환 로직을 포함할 수 있다.

핵심 동작 원리

  1. autoResultMap이 true일 경우 MP는 엔티티 구조 기반으로 ResultMap을 생성
  2. 해당 맵은 @TableField(typeHandler=...)로 지정된 핸들러를 반영
  3. 쿼리 실행 시 직렬화/역직렬화 로직이 적용됨

실제 코드 예제

먼저 JSON에 매핑될 도메인 클래스를 정의한다:

public class UserPreference {
    private String language;
    private Boolean pushEnabled;
    private String themeMode;

    // getter/setter 생략
}

엔티티 클래스에서는 JSON 컬럼에 핸들러를 지정하고 autoResultMap을 활성화:

@TableName(value = "user_profiles", autoResultMap = true)
public class UserProfile {
    @TableId
    private Long id;
    
    private String username;
    
    @TableField(typeHandler = JacksonTypeHandler.class)
    private UserPreference preferences;
    
    @TableField(typeHandler = JacksonTypeHandler.class)
    private List<String> roles;
}

글로벌 설정 (application.yml):

mybatis-plus:
  type-handlers-package: com.example.handler
  type-aliases-package: com.example.entity

사용 조건 및 주의사항

  • 핸들러 필수: autoResultMap만 설정하면 무용지물. 반드시 @TableField(typeHandler=...) 함께 사용
  • 성능 고려: ResultMap 생성 오버헤드 존재. 단순 매핑에는 비활성화 권장
  • XML 매퍼 사용 시: 직접 resultMap을 작성해야 하며, typeHandler를 명시해야 함
  • 지원 버전: 3.3.1 이상에서 안정적으로 작동

활성화가 필요한 상황

사용 사례 autoResultMap 필요 여부
기본 타입 (Long, String 등) 불필요
DB JSON → Java 객체 필수
DB JSON → List/Map 필수
암호화 저장 필드 필수
커스텀 직렬화 로직 필수

결론

MySQL의 JSON 컬럼을 효과적으로 활용하려면 데이터베이스 차원의 기능과 ORM 프레임워크의 매핑 기능을 적절히 결합해야 한다. MyBatis-Plus에서 autoResultMap = true는 JSON 타입을 자바 객체로 자연스럽게 바인딩하기 위한 핵심 설정이며, JacksonTypeHandler와 같은 직렬화 핸들러와 함께 사용되어야 완전한 기능을 발휘한다.

태그: MyBatis-Plus MySQL JSON TypeHandler JacksonTypeHandler autoResultMap

6월 12일 17:09에 게시됨