Spring JPA Custom AttributeConverter


목적

  • JPA Entity Attribute <-> Database Column 커스텀

상세

  • JPA를 사용하여 서버를 개발하다 보면 Database에 저장된 값을 Java 프로그램 내부에서 특정 형태로 변환하여 사용하고 싶을 때가 있다.
  • 예, Database에서 사용 가능한 요일을 1,2,3으로 표현하고 있지만 Java 프로그램 내부에서는 Enum Type으로 변경하여 MONDAY,TUESDAY,WEDNESDAY로 처리하고 싶을 경우.
  • Database -> Entity
  • Entity -> Database

인터페이스

  package javax.persistence;
  
  /**
   * A class that implements this interface can be used to convert
   * entity attribute state into database column representation
   * and back again.
   * Note that the X and Y types may be the same Java type.
   *
   * @param X the type of the entity attribute
   * @param Y the type of the database column
   *
   * @since Java Persistence 2.1
   */
  public interface AttributeConverter<X,Y> {
  	/**
  	 * Converts the value stored in the entity attribute into the
  	 * data representation to be stored in the database.
  	 *
  	 * @param attribute the entity attribute value to be converted
  	 * @return the converted data to be stored in the database column
  	 */
  	public Y convertToDatabaseColumn (X attribute);
  
  	/**
  	 * Converts the data stored in the database column into the
  	 * value to be stored in the entity attribute.
  	 * Note that it is the responsibility of the converter writer to
  	 * specify the correct dbData type for the corresponding column
  	 * for use by the JDBC driver: i.e., persistence providers are
  	 * not expected to do such type conversion.
  	 *
  	 * @param dbData the data from the database column to be converted
  	 * @return the converted value to be stored in the entity attribute
  	 */
  	public X convertToEntityAttribute (Y dbData);
  }

구현

  • AttributeConverter를 implements 후 convertToDatabaseColumn와 convertToEntityAttribute 메소드를 Override해서 사용한다.
  • 항상 적용되는 것을 원할 경우 @Converter(autoApply = true)를 사용한다.

    @Slf4j
    @Converter(autoApply = true)
    public class PayTypeConverter implements AttributeConverter<PayType, String> {
      
        @Override
        public String convertToDatabaseColumn(PayType payType) {
      
            if (isNull(payType)) {
                return null;
            }
      
            return payType.getCode();
        }
      
        @Override
        public PayType convertToEntityAttribute(String code) {
      
            if (isNull(code)) {
                return null;
            }
      
            try {
                return PayType.fromCode(code);
            } catch (IllegalArgumentException e) {
                AttributeConvertException ace = new AttributeConvertException(e);
                log.error("failure to convert cause unexpected code [{}]", code, ace);
                throw ace;
            }
        }
    }
    

활용

  • 레거시 DB의 Column Type이 부적절(?) 할 경우, 서버 쪽에서 반드시 그것을 따를 필요가 없다고 생각한다.
  • 서버 내부에서는 Enum Type이나 특정 형태로 Attribute를 관리하고 DB에 입출력을 할때 String 혹은 Long 형태로 변환하면 좀더 가독성 있는 코드를 만들 수 있을 것으로 보인다.

pkgonan

서버 개발자 Github Linkedin Facebook

Java 및 Spring을 활용한 서버 개발과 성능 튜닝에 관심이 있습니다. 객체지향 및 테스트 코드 작성을 중요하게 생각하며, 변화에 강한 코드를 작성하고자 노력하고 있습니다.