[JPA] org.springframework.dao.DataIntegrityViolationException: could not execute statement 오류 해결
반응형
에러 상황
JPA를 사용하여 개발하던 중 먼전 delete 호출하고 insert를 호출하는 로직 개발 중에 DataIntegrityViolationException, DataException 에러가 발생했다.
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a];
nested exception is org.hibernate.exception.DataException: could not execute statement
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:280)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:566)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)
at jdk.internal.reflect.GeneratedMethodAccessor79.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:128)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
at jdk.proxy2/jdk.proxy2.$Proxy126.commit(Unknown Source)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:152)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258)
오류 내용을 살펴보면 데이터 무결성 관련 위반 에러로 확인할 수 있었다.
데이터를 삭제 후 다시 insert를 하려고 하니 발생한 에러였다.
testRepository.deleteAll();
testRepository.saveAll(testList);
원인
Execute all SQL (and second-level cache updates) in a special order so that foreign-key constraints cannot be violated:
- Insert, in the order they were performed
- Updates
- Deletion of collection elements
- Insertion of collection elements
- Deletes, in the order they were performed
외래 키 제약조건을 위반하지 않기 위해 모든 SQL문이 위와 같은 순서로 동작한다.
insert가 가장 먼저 실행되고 마지막으로 delete가 실행되기 때문에
delete 후 insert를 하게 되면 에러가 발생하게 된 것이다.
해결방법
데이터를 삭제하고 flush 호출한 뒤에 insert를 호출하면 된다.
testRepository.deleteAll();
testRepository.flush();
testRepository.saveAll(testList);
deleteAll, flush, saveAll 순으로 변경했더니 쿼리가 정상적으로 실행되는 것을 확인할 수 있었다.
반응형