JPA

(JPA) Error attempting to apply AttributeConverter 에러 관련 글(feat. @Converter 사용시)

쿠카이든 2022. 3. 26. 13:07
728x90
  • 컬럼에서 DB에 데이터를 변환하는 @Converter 어노테이션을 쓰다가 아래와 같은 에러와 마주치게 되었다. 
    • JpaSystemException: Error attempting to apply AttributeConverter 
    • 이를 해결하기 위해 Converter를 구현하는 인터페이스를 살펴보기로 했다.

 

  • JpaAttributeConverter 인터페이스와 구현체

  • JpaAttributeConverterImpl 는 JpaAttributeConverter 인터페이스의 표준 구현체이다.
  • attributeConverterBean 이라는 멤버변수에  AttributeConverter인터페이스를 구현한 커스텀 컨버터들을 가지고 있다가
  • 경우에 따라서 관계형 값을 도메인 값으로, 도메인 값을 관계형 값으로 변환을 해준다.
package org.hibernate.metamodel.model.convert.internal;

public class JpaAttributeConverterImpl<O,R> implements JpaAttributeConverter<O,R> {
	private final ManagedBean<AttributeConverter<O,R>> attributeConverterBean;
	// ..

	@Override
	public O toDomainValue(R relationalForm) {
		return attributeConverterBean.getBeanInstance().convertToEntityAttribute( relationalForm );
	}

	@Override
	public R toRelationalValue(O domainForm) {
		return attributeConverterBean.getBeanInstance().convertToDatabaseColumn( domainForm );
	}
  • 이 변환은 값을 추출하는 일을 맡고 있는 ValueExtractor 인터페이스의 extract 과정 안에서 수행된다.
package org.hibernate.type.descriptor;

public interface ValueExtractor<X> {
	public X extract(ResultSet rs, String name, WrapperOptions options) throws SQLException;

	public X extract(CallableStatement statement, int index, WrapperOptions options) throws SQLException;

	public X extract(CallableStatement statement, String[] paramNames, WrapperOptions options) throws SQLException;
}
  • 구현체는 별도로 없이 AttributeConverterSqlTypeDescriptorAdapter 클래스의 익명클래스에 의해 수행되는데 코드의 일부는 아래와 같다.
package org.hibernate.type.descriptor.converter;

public class AttributeConverterSqlTypeDescriptorAdapter implements SqlTypeDescriptor {
	// ...
    @SuppressWarnings("unchecked")
    private X doConversion(Object extractedValue) {
        try {
            X convertedValue = (X) converter.toDomainValue(extractedValue);
            log.debugf("Converted value on extraction: %s -> %s", extractedValue, convertedValue);
            return convertedValue;
        } catch (PersistenceException pe) {
            throw pe;
        } catch (RuntimeException re) {
            throw new PersistenceException("Error attempting to apply AttributeConverter", re);
        }
    }
};
  • 제일 아래에 doConversion에 보면 converter.toDomainValue 부분이 있다.
  • 위의 경우에는 DB -> Object 로 가는 경우라서 ValueExtractor가 사용되는데 반대로 Object -> DB 로 가는 경우라면 ValueBinder 에 의하여 converter.toRelationalValue 가 수행된다.

 

catch (RuntimeException re) {
	throw new PersistenceException( "Error attempting to apply AttributeConverter", re );
}
  • 여기에 엔티티의 관계형값과 도메인값에 NULL이 입력되거나 변환이 불가능하면 Error attempting to apply AttributeConverter 오류가 발생한다.

 


출처: https://namocom.tistory.com/892 [나모의 노트]

 

728x90