최대 절전 모드 및 버전 관리에 문제가 있습니다. 나는 Hibernate 3.6.7-Final을 사용하고있다. 여기 내 DAO 클래스의 코드는 (그것이 @Transactional 어노테이션을 사용하는 스프링 빈에 의해 호출되는, 그래서 자체에는 트랜잭션되지 않지만, StaleObjectStateException을 강제로 플러시를 사용하는)입니다 :최대 절전 모드 - StaleObjectStateException으로 인해 실패한 업데이트를 다시 시도하면 부실 인스턴스를 계속 저장합니다.
@Override
public void save(User user) {
boolean saved = false;
while (!saved) {
try {
sessionFactory.getCurrentSession().saveOrUpdate(user);
sessionFactory.getCurrentSession().flush();
saved = true;
} catch (StaleObjectStateException exc) {
sessionFactory.getCurrentSession().refresh(user);
}
}
}
<version name="version" access="field" column="version" type="long" unsaved-value="null" />
문제는 사용자가 저장되지 않습니다, 그리고 코드는 영원히 루프 있다는 것입니다 : 버전은 다음과 같이 매핑 긴 값입니다. 나는 조금 디버깅했고, 최대 절전 모드는 ActionQueue의 개념을 가지고 있으며 내부에는 별도의 콜렉션에 삽입, 업데이트 등이 포함되어 있다는 것이 밝혀졌습니다. 위 코드의 모든 루프에서 업데이트 컬렉션은 1 씩 증가합니다. 컬렉션의 인덱스 0에서 '오래된'업데이트를 항상 실행하려고 시도 할 때 실패하고 그 시점에서 실패합니다. 새로 고친 버전으로 업데이트를 수행하십시오. 이 일을 할 수있는 방법이 있습니까?
내가 원하는 기능에 대한 배경 지식이있을 수 있습니다. 더 똑똑한 사람이 더 좋은 해결책을 제안 할 수 있습니다. 버전 관리가없고 사용자가 잘못된 로그인 수를 포함하는 열을 가지고 있다고 가정 해보십시오. 이 수는 실패 할 때마다 1 씩 증가하며 성공적인 로그인으로 재설정됩니다. (우리는 실패한 x 번의 시도 후에 사용자가 로그인 할 수있는 시간 제한을 도입하여 계정에 무차별 한 공격을 방지하지만 여기는 관련성이 없습니다.) 이제 공격자가 공격을 사용한다고 가정합니다. 동일한 사용자 계정은 서버의 여러 스레드가 액세스 할 수 있으며 2 개의 스레드가 실패 수 (예 : 2)를 읽으면 스레드 1이이를 3으로 업데이트하고 저장 한 다음 스레드 2가이를 3으로 업데이트하고 저장합니다. 우리는 방금 실패한 시도 하나를 잃었습니다. 이것은 버그입니다.
그래서이 문제를 해결하기 위해 위의 스레드 2에서 예외를 throw하는 다른 용도로 사용할 수없는 버전 관리 열을 소개하려고합니다.이 경우 작업이 다시 시도됩니다 (잠재적으로 매우 가능성은 낮다.) - 기본적으로 이것은 낙관적 인 잠금을 기반으로 사용자를 저장하는 직렬화를 도입한다. 앞에서 설명한 것처럼 이것은 작동하지 않습니다.
아무도 나를 도와 줄 수 있습니까? 시작하는 것이 좋은 생각입니까? 어쩌면 더 좋은 방법이 있을까요? 왜 Hibernate 스 니펫이 작동하지 않습니까?
위의 코드를 하나의 스레드로 테스트하고 있습니까? –