2014-02-17 2 views
2

버전 필드를 사용하여 낙관적 잠금을 사용하려고하는데 jpa 저장소에서 저장을 호출해도 예외가 throw되지 않습니다. 나는 봄에 익숙하지 않고 동면하며 나는 그것을 잘못 설정하고 있다고 걱정한다. 내가 사용하고
라이브러리는 다음과 같습니다 hibernate4 - 받는다는 - 플러그인 버전 1.0.2 최대 절전 모드 - jpa02.0 1.0.1 스프링 데이터 JPA 버전 1.3.4버전을 사용하는 Hibernate optimistic 잠금이 작동하지 않습니다.

그래서 내 엔티티는 다음과 같이 설정 :

@Entity 
public class MyEntity 
{ 
    @Id 
    protected Long id; 

    @Version 
    protected Long version; 

    protected String name; 

    public Long getVersion() 
    { 
     return version; 
    } 

    public void setVersion(Long version) 
    { 
     this.version = version; 
    } 

    public Long getVersion() 
{ 
     return version; 
} 

public void setVersion(Long version) 
    { 
     this.version = version; 
    } 

public Long getId() 
    { 
     return id; 
    } 

public void setId(Long id) 
    { 
     this.id = id; 
    } 

    public String getName() 
    { 
    return name; 
    } 

public void setName(Long id) 
    { 
     this.name = name; 
    } 
} 

내 DTO를 통해 클라이언트를 통해 버전을 통과하고 나는 내 MyEntityStoreDao에 저장 할 때를 다시 전달 :

@Repository 
    public class MyEntityStoreDao extends BaseDao<MyEntityStoreDao> 
    { 

     private RepositoryManager myRepoManager; 

     @Autowired 
     public void setMyRepo(MyEntityRepository myRepo) 
     { 
      this.myRepo = myRepo; 
     } 

     public MyEntity save(MyEntityDTO dtoToUpdate) 
     { 
      Session session = this.Session(); 
      MyEntity myEntity = new MyEntity(); 

      if(dtoToUpdate.getId() > 0) { 
      myEntity = (MyEntity) session.get(MyEntity.class, dtoToUpdate.getId()) 
      }  

      myEntity.setName(dtoToUpdate.getName()); 

      MyEntity result = this.myRepo.save(myEntity); 

      this.repositoryManager.flush(myRepo); 

     } 
    } 

repositoryManager BaseDao에 있으며 org.springframework.data.jpa.repository.JpaRepository을 사용 중입니다.

버전이 올바르게 업데이트되고 증가 중입니다. 그러나 업데이트를 수행 할 때 버전이 DTO에서 전달되어 MyEntityStoreDao에 저장되어 데이터베이스에있는 내용과 일치하지 않을 때 StaleStateException 또는 OptmisticLockingException이 발생합니다.

확인했는데 버전이 일치하지 않지만 저장이 여전히 발생합니다. 왜 이런 일이 일어나고 있는지에 대한 도움이 필요하십니까? 업데이트 쿼리가 필요한 경우 쇼 - SQL이 SQL 로깅에 감사

+1

업데이트 코드는 어디에 있습니까? 개체를 업데이트하는 경우 repo에서 saveOrUpdate (object) 메서드를 호출하십시오 – Zeus

+0

자신이 버전을 변경하지 않습니까? 이는 JPA 제공자가 수행해야하는 관리입니다. 이를 테스트하는 적절한 방법은 두 개의 스레드를 생성하는 것인데, 동시에 각각 고유 한 트랜잭션에서 동일한 엔티티를 가져 와서 업데이트합니다. 그 중 하나는 저축 할 때 실패해야합니다. 이것은 커밋하기 전에 스레드에 몇 초간 잠을 자면 쉽게 수행 할 수 있습니다. – Gimby

+0

@Zeus - 업데이트 코드는 jpa 저장소가 저장을 처리하는 곳입니다. – Lumpy

답변

0

를 켜고 = true로 볼 where 절

where version = ? 

절은 당신이 주석에게 @org.hibernate.annotations.Entity(dynamicUpdate = true)

+0

버전을 인쇄합니다. 업데이트 myTable 버전 =?, 이름 =? 여기서 id =? 및 버전 =? dynamicUpdate = true는 더 이상 사용되지 않습니다. – Lumpy

+0

그것이 작동하는지 여부를 확인하기 위해 dynamicUpdate = true를 추가하십시오. –

+0

클래스의 주석이있는 MyEntity 권한에 dynamicUpdate = true를 추가했습니다. 그것은 더 이상 사용되지 않습니다. 그러나 그것은 효과가 없었습니다. @Entity @ org.hibernate.annotations.Entity (dynamicUpdate = true) public class MyEntity { – Lumpy

0

를 추가 할 필요가 다음 누락 된 경우 등의 경우, 업데이트 된 코드와

MyEntity myEntity = new MyEntity(); // You dont need to initalize 

      if(dtoToUpdate.getId() > 0) { 
      myEntity = (MyEntity) session.get(MyEntity.class, dtoToUpdate.getId()) 
      }  

      myEntity.setName(dtoToUpdate.getName()); 

      MyEntity result = this.myRepo.save(myEntity); 

당신은 녹화가있는 myEntity을 저장하려고 데이터베이스에서 올바른 정보 (올바른 버전). 따라서 오류가 발생하지 않습니다. 당신이 오류가 발생 할 경우 DB에 엔티티를 업데이트 할 때 엔티티 버전 ​​(객체 변수) 테이블의 버전 (필드 같지 않으면, 그래서 기본적으로 ...

public MyEntity save(MyEntityDTO dtoToUpdate) 
    { 
     Session session = this.Session(); 
     MyEntity myEntityV1 = null; 
     MyEntity myEntityV2 = null; 

     // Getting v1 and V2. at this time both V1 & V2 will have same version (assume version as 5) 
     if(dtoToUpdate.getId() > 0) { 
     myEntityV1 = (MyEntity) session.get(MyEntity.class, dtoToUpdate.getId()) ; 
     myEntityV2 = (MyEntity) session.get(MyEntity.class, dtoToUpdate.getId()) ; 
     }  

     myEntityV1.setName(dtoToUpdate.getName()); 

     // Saving V1 will reflect the increase in version (actual row will be version of 6) 
     MyEntity result = this.myRepo.save(myEntityV1); 

     myEntityV2.setName("some changes"); // change some in V2instance. So that hibernate/Jpa will capture the change 
     this.myRepo.save(myEntityV2); // You will get exception. because the v2 has version as 5. but the row was updated . 

     this.repositoryManager.flush(myRepo); 

    } 

를 다음을 수행하십시오) 데이터베이스에서 (이 업데이트 전에) 예외가 발생합니다

+0

코드는 테스트 용도로 사용됩니다. 당신이 그것을 시험하기 위하여 진술 한대로 정확하게했다. 2 개의 엔티티를 생성하고 동시에 두 개를 검색했습니다. 첫 번째 내용을 저장 한 다음 두 번째 내용을 저장하면 두 번째 항목이 올바르게 저장되고 버전도 올바르게 업데이트됩니다. 예외가 발생하지 않았습니다. 정확한 코드에서 버전은 한 번만 업데이트되고 버전은 한 번 증가되었습니다. 각 save 후에 repoManager.flush를 추가하면 두 번 증가합니다. 그래서 당신의 예제에서 코드는 버전 6이되었고 "약간의 변화"라는 이름은 db에 있습니다. 플러시 라인을 두 번 사용하면 버전은 7입니다. – Lumpy

+0

첫 번째 엔티티를 수정하지 않았다고 생각합니다. 이미 show-sql = true로 설정 한 경우 쿼리에서 두 개의 업데이트를 보았습니까? 그리고 당신은 당신에게 두 번 플러시가있을 때 예외가 없었어요? 나는 트랜잭션 주석에 의해 PersistentManagr surronded를 사용하여 이슈를 시뮬레이트했으며, 예외로 작동한다. – Mani

+0

하나의 flush와 2 번의 두 인스턴스 모두에 대해 기록 된 2 개의 update sql이있었습니다. 그러나 여전히 예외는 없습니다. 나는 왜 여전히 불확 실한 지, 나는 지금 당황하고있다. 지금까지 의견을 보내 주셔서 감사합니다. – Lumpy

관련 문제