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
'JPA' 카테고리의 다른 글
영속성 전이에 관해(부제 : CASCADE) (0) | 2022.06.11 |
---|---|
상속관계 매핑 전략(@DiscriminatorColumn 란?) (0) | 2022.06.05 |
JPA에서 pageable을 통해 Paging 간단하게 구현하는 법 (0) | 2022.03.22 |
(스프링 시큐리티)UserDetailsService, UserDetail (0) | 2022.02.17 |
(스프링 데이터 JPA) 페이징과 정렬 (0) | 2022.02.15 |