使用版本的Hibernate乐观锁定无法正常工作

时间:2014-02-17 15:10:29

标签: java spring hibernate jpa

我正在尝试使用版本字段使用乐观锁定,当我从jpa存储库调用save时,不会抛出任何异常。我是Spring和hibernate的新手,我担心我的设置不正确 我使用的库是: hibernate4-maven-plugin版本1.0.2 hibernate-jpa02.0 1.0.1 spring-data-jpa 1.3.4版

所以我的实体设置如下:

@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。

我检查过并且版本不匹配,但仍然会发生保存。有关为什么会发生这种情况的任何帮助?感谢

2 个答案:

答案 0 :(得分:1)

通过show-sql = true启用sql日志记录,并查看更新查询是否具有所需的where子句

where version = ?

如果缺少此类where子句,则需要添加注释@org.hibernate.annotations.Entity(dynamicUpdate = true)

答案 1 :(得分: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,其中包含数据库中的最新信息(正确版本)。所以你不会得到任何错误。如果您想产生错误,请执行以下操作..

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);

   }

所以基本上当你在Db中更新实体时,如果实体版本(对象中的变量)不等于数据库中的版本(表中的字段)(在此更新之前),它将抛出异常