[SPRING] 최대 절전 모드에서 예외를 throw하지 않는 DB 제약 위반
SPRING최대 절전 모드에서 예외를 throw하지 않는 DB 제약 위반
다음 코드가 있습니다.
try {
userDAO1.save(userRecord);
userDAO2.save(userRecord);
}
catch(DataIntegrityViolationException e) {
throw new ApplicationException("Contraint violated")
}
userDAO1.save (userRecord)는 무결성 제약 조건을 위반하므로 전체 코드가 실행 된 후 userDAO1이 참조하는 테이블에 아무 것도 기록되지 않습니다.
그러나 userDAO1.save () 문은 오류 / 예외를 throw하지 않으므로 userDAO2.save ()도 실행됩니다.
그러나 DataIntegrityViolationException이 잡히고 스택 추적이 null입니다.
UserDAO1.save ()가 제약 조건을 위반하면, DataIntegrityViolationException이 어디에서 던져 졌는지 확인하고 userDAO2.save ()가 실행되지 않도록하려면 어떻게해야합니까?
이 코드 주위에 @Transactional 주석을 추가하려고 시도했지만 그 중 하나도 작동하지 않았습니다.
스택 추적 :
org.springframework.dao.DataIntegrityViolationException: ORA-00001: unique constraint (UNIQUE_EMAIL) violated
; SQL [n/a]; constraint [UNIQUE_EMAIL]; nested exception is org.hibernate.exception.ConstraintViolationException: ORA-00001: unique constraint (UNIQUE_EMAIL) violated
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:643)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:104)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:516)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy76.updateUser(Unknown Source)
at com.osiris.UserReg.UpdateUserCommand.execute(UpdateUserCommand.java:63)
내가 게시 한 코드는 @Transactional (rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)으로 주석 된 UpdateUserCommand에 있습니다.
해결법
-
==============================
1.좋아, 이건 좀 까다 롭긴하지만 최선을 다할거야. Hibernate는 @Transactional으로 주석 된 메소드가 종료 될 때만 트랜잭션을 커밋 할 것이다. 따라서 DataIntegrityViolationException은 해당 메서드가 반환 된 후에 만 catch 할 수 있습니다. 당신이 UserDAO2.save ()를 호출하지 않을 수있는 방법은 없다. 왜냐하면 그것이 위반이 발생했다는 것을 탐지 할 수 없기 때문이다. 아래 예제를 제공합니다.
좋아, 이건 좀 까다 롭긴하지만 최선을 다할거야. Hibernate는 @Transactional으로 주석 된 메소드가 종료 될 때만 트랜잭션을 커밋 할 것이다. 따라서 DataIntegrityViolationException은 해당 메서드가 반환 된 후에 만 catch 할 수 있습니다. 당신이 UserDAO2.save ()를 호출하지 않을 수있는 방법은 없다. 왜냐하면 그것이 위반이 발생했다는 것을 탐지 할 수 없기 때문이다. 아래 예제를 제공합니다.
@Service /*These variable names are used for clarity's sake, I don't actually use these names myself*/ public UserServiceImpl implements UserService{ @Autowired private HibernateUserDAO1 userDao1; @Autowired private HibernateUserDAO2 userDao2 @Transactional /*Put your try catch block around where this method is called*/ public void saveUserDao1(User user){ userDao1.saveOrUpdate(user); } @Transactional /*Only call this if saveUserDao1 succeeds*/ public void saveUserDao2(User user){ userDao2.saveOrUpdate(user) } }
그런 다음 당신의 HibernateUserDAO1에서 :
public void saveOrUpdate(User user){ currentSession().saveOrUpdate(user); }
예외는 서비스 계층 위에서 만 발견 할 수 있습니다. 이상적으로하고 싶은 일은 두 가지 DAO를 사용하여 개별 저장하고 두 번째 DAO를 수행하기 전에 먼저 성공했는지 확인하는 것입니다.
편집 : 또한 Hibernate는 @Transactional로 주석 된 private 메소드를 선택하지 않을 것이라는 점에 유의해야한다. 왜냐하면 Hibernate는 클래스가 구현하는 인터페이스로부터 Proxy 객체를 생성하기 때문이다. 인터페이스 정의 없음 = 프록시 객체 없음 = 최대 절전 모드 세션 없음. 따라서 @Transactional 주석이 달린 개인 메소드를 호출 할 수 없습니다. SessionFactory를 추상적 인 수퍼 클래스에 객체로 만들고 DAO의 두 인스턴스를 상속 받도록하려고합니다. 더 나은 옵션은 각각 다른 데이터베이스를 가리키는 2 개의 트랜잭션 관리자를 사용하고 어떤 데이터베이스가 저장되는지 지정하는 것입니다. 그렇게하면 DAO를 1 개만 사용할 수 있고 저장을 수행하는 데 필요한 세션 팩터 리를 사용할 수 있습니다.
-
==============================
2.userDAO1.save () 문이 실행되는 동안 DataIntegrityViolationException이 발생하지 않았다고 생각하는 이유가 무엇입니까? 또한, userDAO2.save ()가 실행되었다고 생각하는 이유는 무엇입니까?
userDAO1.save () 문이 실행되는 동안 DataIntegrityViolationException이 발생하지 않았다고 생각하는 이유가 무엇입니까? 또한, userDAO2.save ()가 실행되었다고 생각하는 이유는 무엇입니까?
Eclipse Eclipse와 같은 IDE 디버그 콘솔에서 코드 실행 진행을 관찰 한 결과 위의 의견이 나온 경우 해석이 잘못되었을 수 있습니다.
아래에있는 것과 같은 디버그 문을 펀치 인하 고 코드를 실행하여 결과를 관찰하십시오. 이것은 장애의 근본 원인을 찾아내는 데 도움이 될 수 있습니다.
try { userDAO1.save(userRecord); System.out.println("-- After userDAO1.save(userRecord) --"); userDAO2.save(userRecord); System.out.println("-- After userDAO2.save(userRecord) --"); } catch(DataIntegrityViolationException e) { e.printStackTrace(); throw new ApplicationException("Contraint violated") }
from https://stackoverflow.com/questions/21822663/db-constraint-violation-not-throwing-exception-in-hibernate by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring Data로 특정 항목을 볼 때만 특정 필드를 노출합니까? (0) | 2019.05.05 |
---|---|
[SPRING] 동일한 애플리케이션에서 스프링 보안 양식 로그인 및 oauth2 (0) | 2019.05.05 |
[SPRING] spring-data-couchbase를 사용하고 있지만 메서드 이름의 쿼리 작성이 작동하지 않습니다. (0) | 2019.05.04 |
[SPRING] Spring Batch로 여러 열의 CSV 파일을 읽는 법 (0) | 2019.05.04 |
[SPRING] 'hibernate.dialect'가 설정되지 않았을 때 연결은 null 일 수 없다. hibernate4 tomcat7 (0) | 2019.05.04 |