STUDY/Spring
JPA | @Converter, @Convert (+ @Convert 먹히지 않을 때)
개미606
2021. 11. 1. 17:46
지금 하는 프로젝트가 레거시 디비를 이용해야 하는데.. 데이터 베이스 구조나 값을 변경할 수는 없고..
1, 2 등에 해당하는 값을 일일이 찾아보는 것도 귀찮아서 ENUM으로 변환해서 사용하고자 한다..
ENUM 정의
예를 들어 1은 진돗개, 2는 삽살개...를 의미한다고 할 때..
대충 이런 구조의 ENUM
을 정의할 수 있다.
@Getter
public enum DogBreed {
JINDO(1, "진돗개"),
SAPSAL(2, "삽살개");
private int num;
private String name;
Animal(int num, String name) {
this.num = num;
this.name = name;
}
}
한 두개 일 때는 외울만 하지만 값도 여러개에 테이블마다 1, 2, 3... 이렇게 계속 있으면 짜증나니까..
이럴 때 @Converter
와 @Convert
를 사용하면 짱짱굿
ENUM에서 디비 값으로 상수를 찾는 함수를 작성
디비에는 숫자로 저장되어 있기 떄문에 해당 숫자로 상수를 찾는 함수를 만든다.
여기까지만 하면 거의 끝
public static DogBreed ofNum(Integer ogNum) {
return Arrays.stream(DogBreed.values())
.filter(val -> val.getNum() === ogNum)
.findAny()
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 동물이네요.."));
}
@Converter 작성
클래스 선언부에 @Converter
애너테이션을 등록한 뒤 AttributeConverter
를 구현하면 된다.
두 개의 메서드를 오버라이딩 하면 끝!convertToDatabaseColumn()
메서드는 이름만 봐도 알 수 있듯 어떤 값을 디비에 저장할지 알려주는 거다..
디비에 1, 2, 3.. 이런 숫자를 저장해야 하므로 getNum()
을 해준다.
Wrapper Class로만 작성할 수 있다.
@Converter
public class BreedConverter implements AttributeConverter<DogBreed, Integer> {
@Override
public Integer convertToDatabaseColumn(DogBreed attribute) {
return attribute.getNum();
}
@Override
public DogBreed convertToEntityAttribute(Integer dbData) {
return DogBreed.ofNum(dbData);
}
}
Entity에서 @Convert애너테이션으로 등록
@Convert
애너테이션으로 작성한 컨버터 클래스를 등록하면 끝이다..
@Entity
public class AnimalHistory {
@Convert(converter = BreedConverter.class)
private DogBreed breed;
}
@Id
컬럼에서 사용할 때
@Id
와 @Convert
를 함께 사용하면 안먹힌다. 그냥 몇 번째 값인지만 등록됨..
부득이하게 함께 사용해야 할 경우에는 @IdClass()
를 사용할 수 있다.
@Column()
도 IdClass에 정의해야 함!
@IdClass(AnimalHistoryId.class)
@Entity
public class AnimalHistory {
@Id
private DogBreed breed;
}
@AllArgsConstructor
@NoArgsConstructor
public class AnimalHistoryId implements Serializable {
@Column(name = "DOG_BREED", nullable = false)
@Convert(converter = BreedConverter.class)
private DogBreed breed;
// equals and hashcode 오버라이딩 필수
}