오늘은 에러 로그 관련해서 포스팅을 진행하려고 합니다.
개발 도중에 발생한 Error log인데, Error log를 먼저 보여드리고 분석한 내용에 대해 설명드리겠습니다.
Error log
org.springframework.orm.jpa.JpaSystemException: Error attempting to apply AttributeConverter; nested exception is javax.persistence.PersistenceException: Error attempting to apply AttributeConverter
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:418)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:227)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:436)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:131)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
at com.sun.proxy.$Proxy212.save(Unknown Source)
at com.piolink.cc.app.alarm.service.AbstractAlarmService.saveAlarmNow(AbstractAlarmService.java:123)
at com.piolink.cc.app.alarm.service.AbstractAlarmService.saveAlarmNow(AbstractAlarmService.java:123)
at com.piolink.cc.app.alarm.service.AbstractAlarmService.saveAlarm(AbstractAlarmService.java:111)
at com.piolink.cc.app.alarm.service.IpConflictAlarmService.alarm(IpConflictAlarmService.java:45)
at com.piolink.cc.app.ndm.service.NdmService.conflict(NdmService.java:226)
at com.piolink.cc.app.ndm.service.NdmService$$FastClassBySpringCGLIB$$cb7d533e.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:651)
at com.piolink.cc.app.ndm.service.NdmService$$EnhancerBySpringCGLIB$$e851a393.conflict(<generated>)
at com.piolink.cc.app.ndm.service.NdmRouteService.route(NdmRouteService.java:61)
at com.piolink.cc.app.ndm.service.NdmRouteService.event(NdmRouteService.java:38)
...
간략히 읽어봤을 때, AttributeConverter를 적용하려고 시도했지만 실패하게 돼서 발생한 에러라는 것을 확인할 수 있습니다.
이제 여기에서 Converter라는 개념이 나왔는데, 무엇인지 간단히 짚고 넘어가도록 하겠습니다.
@Converter
- Entity에 Data를 변환하여 DB에 저장할 수 있게 해주는 annotation
- Convert를 적용할 필드에 @Convert 어노테이션과 만들어준 Convert class를 지정해 주면 됩니다
Converter 생성 방법
- AttributerConverter의 convertToDatabaseColumn, convertToEntityAttribute 메서드를 override 해주어야 합니다.
- Entity ↔ DB 간의 데이터 변환이 가능해집니다.
Example
@Converter(autoApply = true) // global 설정
public static class DeviceTypeConverter implements AttributeConverter<DeviceType, Integer> {
@Override
public Integer convertToDatabaseColumn(DeviceType deviceType) {
return deviceType.getType();
}
@Override
public DeviceType convertToEntityAttribute(Integer deviceType) {
return DeviceType.getType(deviceType);
}
}
다음과 같은 컨버터를 어떠한 필드에 적용할 때, 변환이 실패해서 Error attempting to apply AttributeConverter 에러가 발생하게 됩니다.
관련 클래스를 간단히 살펴보도록 하겠습니다.
ValueBinder
- Object -> DB로 Data 변환
ValueExtractor
- DB -> Object로 데이터 변환
위의 데이터 변환 메서드를 참고했을 때, 해당 메서드의 try ~ catch 문에서 엔티티의 값, 도메인 값에 Null이 들어가거나 변환이 불가능하면, 발생하는 Error입니다.
해당 Error를 해결하기 위해, DB <-> Entity의 변환 과정에서 null 처리를 해주면 간단히 해결할 수 있게 됩니다.
'Java > Spring' 카테고리의 다른 글
[Spring] Spring Cloud Gateway (+ Eureka Server) (1) | 2024.10.26 |
---|---|
[Spring] Spring Webflux (1) | 2024.10.23 |
[Spring] @Transactional isolation level, propagation level, timeout (5) | 2024.09.23 |
[Spring] Spring Security 동작 원리 파악 (id, pw 기반의 basic auth 방식) (0) | 2024.09.06 |
[Spring] org.hibernate.AssertionFailure: null id in entry (don't flush the Session after an exception occurs) (0) | 2024.09.04 |