최대 절전 모드에서 EJB 3을 사용하고 있습니다. 나는 스테이트리스 세션 Bean을 가지고있다. 해당 빈에 deleteItem 메소드가 있습니다.최대 절전 모드 OptimisticLockException 캐치 실패
클라이언트가 deleteItem 메소드를 호출하면 문제없이 삭제가 발생합니다. 하지만 for 루프를 사용하여 deleteItem 메서드를 호출하고 해당 루프의 한계를 5-10 번 설정하려고하면 삭제가 실패하는 경우가 있습니다. 하지만 항상 그런 것은 아닙니다.
삭제 작업은 실제로 2 개의 테이블에서 데이터를 삭제합니다. 자식 테이블과 부모 테이블 각 삭제는 플러시 작업을 수행하여 커밋됩니다.
내가 이미 하나씩 삭제를 실행하면 문제가 발생하지 않는다는 것을 이미 언급했듯이, 동시에 실행하려고 할 때만 발생합니다. 내가 받고있는 예외는 다음과 같습니다
Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key
constraint fails (`functionTest/MotherTable`, CONSTRAINT `FKBC6CB0E6D5545EFD` FOREIGN KEY
(`MotherTable_FieldId`) REFERENCES `ChildTable` (`childTableId`))
여기서 동시 삭제 작업을 수행 할 방법이 없습니다. 그리고 항목 삭제는 다른 항목 삭제 작업과 관련이 없습니다. 동시성이 여전히 발생하면 동시에 여러 항목을 삭제해도 문제가되지 않습니다.
따라서 "클라이언트가 여러 스레드에서 동일한 Bean 인스턴스에 액세스하고있을 수 있습니다."라는 결론이났습니다. 이러한 상황에서 두 스레드는 동일한 Entity Manager State를 다른 상태로 유지합니다. 하나는 아직 다른 항목이 자식 항목 제거가 완료되지 않은 경우 지속성 컨텍스트를 플러시하려고 시도합니다. 그 시점에서 BatchUpdateException이 발생했습니다. - 내 관찰이야. 나는 100 % 확실하지 않다.
이 상황을 극복하기 위해 낙관적 잠금을 사용했습니다. 내가 어머니 테이블에 버전 열을 만들었습니다. 이제 OptimisticLockException이 발생합니다. 그러나 나는 예외를 잡을 수 없다. 아래는 OptimisticLockException을 잡기 위해 사용하는 코드입니다.
private boolean deleteItem(Item itemId) {
Item item= getItem(itemId);
removeChildTableData(item);
mEm.remove(item);
try
{
mEm.flush();
}
catch (OptimisticLockException e)
{
try {
Thread.sleep(1000);
}
catch (InterruptedException e1) {
e1.printStackTrace();
}
deleteItem(itemId);
}
catch(Exception ex)
{
if (ex.getCause() instanceof OptimisticLockException)
{
try {
Thread.sleep(1000);
} catch (InterruptedException x) {
}
deleteItem(itemId);
}
}
return true;
}
내 목표는 OptimisticLockException을 잡아서 다시 삭제 작업을 다시 실행하는 것입니다. 예외 클래스 이름을 확인했으며 EntityNotFound입니다. 하지만 stacktrace에서 StaticObjectStateException뿐만 아니라 OptimisticLockException을 얻고 있음을 알 수 있습니다.
그럼, 아무도 내게이 OptimisticLockException을 잡아 야하는 방법을 안내해 줄 수 있습니까?
중요한 점은 어디에서 예외가 발생하는지 전체 스택 추적이 많은 도움이 될 것이라고 생각합니다. – wildhemp
오류 메시지의 내용을 신뢰할 수 있어야합니다. 외래 키 제약 조건이 깨 졌다고하면 외래 키 제약 조건이 깨졌습니다. 낙관적 인 사랑을 추가해도 아무런 변화가 없습니다. 그리고 낙관적 인 잠금 예외를 잡아서 같은 세션과 엔티티를 계속 사용해서는 안됩니다. 그것은 작동하지 않습니다. http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#transactions-demarcation-exceptions을 읽으십시오. –
@JBNizet - 귀하의 요지를 이해했습니다. 그러나 문제는 그것이 항상 일어나지 않는다는 것입니다. 동시성이 발생할 때만 발생합니다. 그리고 네가 맞습니다. 낙관적 인 락 예외를 처리 한 후에 새로운 트랜잭션에서 실행해야합니다. – ifti24