JPA를 이용해서 코딩 장난을 하던 중 도메인 모델상의 InetAddress를 DB 테이블의 VARCHAR 타입 컬럼에 매핑해야 할 요구가 생겼다. JPA 2.1 버전을 사용하고 있었는데, JPA 2.1에서 제공하는 AttributeConverter라는 걸 사용하면 매우 간단하게 InetAddress 프로퍼티 타입과 DB VARCHAR 타입 사이의 매핑을 처리할 수 있는 걸 알 수 있었다.
사용법은 간단하다. 먼저 AttributeConverter 인터페이스를 구현한 컨버터 클래스를 구현현다.
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import java.net.InetAddress;
import java.net.UnknownHostException;
@Converter
public class InetAddressConverter implements AttributeConverter<InetAddress, String> {
@Override
public String convertToDatabaseColumn(InetAddress attribute) {
if (attribute == null)
return null;
else
return attribute.getHostAddress();
}
@Override
public InetAddress convertToEntityAttribute(String dbData) {
if (dbData == null || dbData.isEmpty()) return null;
try {
return InetAddress.getByName(dbData);
} catch (UnknownHostException e) {
throw new RuntimeException(String.format(
"InetAddressConverter fail to convert %s to InetAddress: %s", dbData, e.getMessage()),
e);
}
}
}
AttributeConverter의 타입 파라미터에서 첫 번째 타입 파라미터는 자바쪽의 프로퍼티 타입을, 두 번째 타입 파라미터는 DB의 컬럼 타입을 의미한다. 위 코드의 경우 자바 모델에서 사용할 InetAddress 타입 프로퍼티와 DB 테이블에서 사용할 문자열 타입 간의 변환을 처리하는 컨버터를 구현한 것이다.
컨버터를 구현했으면, JPA의 매핑 클래스에서 @Convert 애노테이션을 사용해서 값을 변환대상 프로퍼티에 컨버터를 지정해주면 된다.
import javax.persistence.Convert;
@Entity
public class IpRange {
@Column(name = "RANGE_FROM")
@Convert(converter = InetAddressConverter.class)
private InetAddress from;
이제 JPA는 InetAddress 타입의 from 프로퍼티 값을 DB에 저장할 때 InetAddressConverter를 이용해서 문자열로 변환한 뒤에 저장한다. 비슷하게 DB에서 값을 읽어올 때 InetAddressConverter를 이용해서 문자열을 InetAddress로 변환해서 from 프로퍼티에 할당한다.