Hibernate:仅当特定字段为空时才更新实体中的字段

时间:2011-04-27 19:54:27

标签: hibernate concurrency locking version

我有以下内容:

public class Member {

    @Id
    @Column
    private String id;

    @Column
    private String location;

    // setters/getters
}

我必须实施以下业务规则:

设置位置:

  1. 根据ID
  2. 从DB获取成员
  3. 如果location为null,请为location分配值并保存,否则不执行任何操作。
  4. 
    public void setLocation(String id, String location){
        Member m = memberDao.find(id); // assume m is not null
        if(null == m.getLocation()){
             m.setLocation(location);
             memeberDao.saveOrUpdate(m);
        }
        else
            throw new MemberAlreadyHasALocationException();
    }
    

    删除位置:

    1. 根据ID
    2. 从DB获取成员
    3. 如果location具有非null值且当前值等于参数值,则将location设置为null并更新,否则不执行任何操作
    4. 
      public void removeLocation(String id, String location){
          Member m = memberDao.find(id);
          if(m.getLocation() != null && m.getLocation.equalsIgnoreCase(location)){
               m.setLocation(null);
               memeberDao.saveOrUpdate(m);
          }
      }
      

      我的任务是处理并发问题,但我不知道如何在hibernate中执行此操作。更具体地说,如果具有该ID的实体当前没有位置,我如何处理对同一ID的setLocation的并发调用。

      基本上,第一次更新应该获胜而第二次更新应该失败。

      向Member类添加版本是否足够

      
      @Version
      @Column(name="version")
      private Long version;
      

      但是,如果有性别字段,我希望能够更新性别字段,而无需关心该位置是否被其他交易更新。

      感谢。

1 个答案:

答案 0 :(得分:0)

  

基本上,第一次更新应该会赢   第二个应该失败。

     

添加版本是否足够   会员班

是的,确实如此。假设您和我使用version = x从数据库中读取实体。我对实体的property1进行了一些更改并提交到数据库。现在,数据库中的实体具有version = x + 1。现在,您更改了实体版本的property2(property1仍保留旧值)。当您将更改的实体更新到数据库时,我对property1所做的更改将会丢失,因为您将使用旧值覆盖它。但是这不会发生,因为Hibernate将检查在读取实体和更新实体之间可能发生的任何更改。当您更新实体时,Hibernate会发现数据库中的实体版本与您提供的实体版本不同。这意味着其他人对该对象进行了一些更改,即您提供的对象是陈旧的,因此抛出了StaleStateException。

  

然而,说有性别   领域,我希望能够   更新性别字段而不关心   如果位置正在更新   另一笔交易。

使用休眠是不可能的(从上面的例子中可以清楚地看出)。如果支持此功能,则在提交包含较旧的location值的性别更新时,将丢失对该位置所做的更改。可以使用一些逻辑和明确的版本检查和更新实体之前更新更改的字段来实现一定程度的宽容,但问题仍然存在,你可以永远不知道在什么时刻变化将对象进行。在我看来,这样的实施将是一种过度杀伤,但效益不足。