티스토리 뷰
사건의 발단
- 예전에 사용하던 MySQL의 데이터를 구해서 새로 작업할 DB에 이식했다.
- 그 중에 지역 정보를 담고 있던
area
라는 테이블의 Entity를 만들다고 JPA의 find관련 메서드로 데이터를 가져오는 부분에서 문제가 발생했다.
area의 스키마

- 다른 건 필요 없고 문제가 생긴 칼럼만 확인해 보자.
Entity 작성
@Entity
@Table(name = "area")
public class AreaEntity {
...
@Enumerated(value = EnumType.String)
@Column(name = "kind")
private Kind kind;
public enum Kind {
TOURISM, LEISURE, CULTURE;
}
}
- 기존에 늘 작성하던대로 다음과 같은 형태로 작성했다.
500
에러가 발생해서 콘솔 로그를 확인해 보니 다음과 같은 오류가 나타났다.nested exception is java.lang.IllegalArgumentException: No enum constant com.study.kokkokapi.persistence.entity.AreaEntity.Kind.culture
- 알아보니
area
테이블의kind
칼럼은enum('tourism', 'leisure', 'culture')
이고 Entity에서 사용하는 enum 값은TOURISM, LEISURE, CULTURE
다.- 한마디로 대소문자가 구분이 되어서 발생하는 에러였다.
- 열심히 구글링을 해보니
Converter
라는 것을 사용하면 이런 변환을 쉽게 할 수 있다고 한다.
Converter 적용
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import javax.persistence.Convert;
@Converter
class KindConverter implements AttributeConverter<AreaEntity.Kind, String> {
@Override
public String convertToDatabaseColumn(AreaEntity.Kind attribute) {
return attribute.toDbValue();
}
@Override
public AreaEntity.Kind convertToEntityAttribute(String dbData) {
return AreaEntity.Kind.from(dbData);
}
}
@Entity
@Table(name = "area")
@Convert(converter = KindConverter.class, attributeName = "kind")
public class AreaEntity {
...
@Column(name = "kind")
private Kind kind;
public enum Kind {
TOURISM, LEISURE, CULTURE;
public String toDbValue() {
return this.name().toLowerCase();
}
public static Kind from(String dbData) {
return Kind.valueOf(dbData.toUpperCase());
}
}
}
KindConverter
를 살펴보면javax.persistence.AttributeConverter<X, Y>
인터페이스를 구현하고 있다.- 여기서 오버라이딩한
convertToDatabaseColumn
메서드는 Entity의 enum을 DB의 enum으로 변환하는 메서드다. - 다른 오버라이딩 메서드인
convertToEntityAttribute
는 DB의 enum을 Entity의 enum으로 변환하는 메서드다.
- 여기서 오버라이딩한
- 현재 DB의 enum이 소문자고 Entity의 enum이 대문자인 상황이다.
- 하려고 했던 작어비 DB 데이터를 조회해서 화면에 전달해주는 작업이기 때문에
convertToEntityAttribute
메서드가 사용된다.- DB에서 가져온 enum 문자열을
toUpperCase()
메서드를 사용해서 대문자로 변환해서 Entity의 Kind enum으로 변환한다.
- DB에서 가져온 enum 문자열을
- 위의 코드를 사용하면 정상적으로 데이터를 가져올 수 있다.
추가 사항
- 기존에 kind에 있던
@Enumerated(value = EnumType.String)
을 그대로 붙이고Converter
를 사용한다면 소용이 없다.- 자세히 공부하지는 않아서 정확하지는 않지만
Converter
는 가져온 데이터를 변환해서 매핑해주는 기능이라고 하면@Enumerated(value = EnumType.String)
은 가져올 때부터 매핑을 해서 가져오기 때문에 에러를 유발하는 것 같다. - 따라서
Converter
를 사용할 때는@Enumerated
를 제거해야 한다.
- 자세히 공부하지는 않아서 정확하지는 않지만
AreaEntity
에서@Convert(converter = KindConverter.class, attributeName = "kind")
에서attributeName
속성을 지정해주지 않으면 어떤 필드에서Converter
를 사용해야할지 모르기 때문에 실행에 실패한다.KindConverter
에 선언된@Converter
라는 애노테이션을 살퍼보면autoApply
라는 속성이 존재하고 기본값은false
다.- 이 속성을
true
로 지정하게 되면 글로벌하게 이Converter
가 적용된다. - 그렇기 때문에
AreaEntity
클래스에서@Convert
를 제거해도 동작한다.
- 이 속성을
- 사실 위에서 발생한 문제는 DB 스키마에서 enum의 항목을 대문자로 변경하면 손쉽게 해결되는 문제다.
Converter
는 대소문자 변환 말고도 여러 곳에서 활용될 수 있기 때문에 정리해봤다.
References
'토이 프로젝트 > 충북 콕! 콕! (Renewal)' 카테고리의 다른 글
개발기 (7) | 2020.08.18 |
---|---|
기술 스택 변경 (0) | 2020.08.15 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- 중간 연산
- jdk14
- 목표
- #예제 #example #가계부 #Account Book
- 계획
- flatMapToInt
- 스트림
- 회고
- java14
- 람다
- flaMap
- Java8
- 자바
- 개발자
- flatMapToDouble
- import문
- IntelliJ
- #배열 #array #map 함수
- 다짐
- 충북 콕! 콕!
- #React #ReactJS #리액트
- Stream API
- 토이 프로젝트
- modern java
- java
- lambda
- flatMapToLong
- 익명 클래스
- 변경사항
- mapToObj
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
글 보관함