0

我的场景是我有两个不同的 API 更新数据库表,一个我们将调用内部和另一个外部,其中一个是用过时的数据覆盖值。

通过 Hibernate 更新的数据当时在应用程序的内存中。如果外部源更新列 (statusCd),而此时它仍在内部应用程序的内存中,则在将其保存在内部应用程序中的那一刻,该值将被陈旧的数据覆盖。

现在我意识到有更多的方法可以解决这个问题,但是我们已经确定,只要可以通过 Hibernate 做到这一点,限制对该对象的 Hibernate 代码的修复是风险最小的。

所以我有两个问题:

  1. 是否可以通过 Hibernate 说“是的,请在创建此列时将此值插入此列,但是,除非该值为‘取消’,否则请不要更新此列中的此值?”
  2. 是否可以在更新之前通过 Hibernate 进行陈旧数据检查,以查看在应用程序内存中时值是否已更改?

以下是相关对象的片段:

@Entity
@Table(name = "Object1")
@XmlRootElement
public class Object1 implements java.io.Serializable {
   private RefObject1Status statusCd;

   @ManyToOne(fetch = FetchType.EAGER)
   @Fetch(FetchMode.JOIN)
   @JoinColumn(name = "statusCd", nullable = false)
   public RefObject1Status getStatusCd() {
      return this.statusCd;
   }
   public void setStatusCd(RefObject1Status cd) {
      this.statusCd = cd;
   }

}

感谢您的时间,

亚历克斯

4

1 回答 1

0

您可以使用http://docs.jboss.org/hibernate/entitymanager/3.5/reference/en/html/listeners.html中描述的 @PreUpdate 方法。在该方法中,您可以将值重置为其原始值,但您需要将原始值保留在另一个属性中。

您可以使用“@Formula”将原始属性映射为计算属性,然后它将在加载期间只读:

   @ManyToOne
   @JoinColumn(name = "statusCd")
   public RefObject1Status statusCd;


   @ManyToOne
   @Formula( value = "statusCd")
   public RefObject1Status origStatusCd;

   @PreUpdate
   public void checkStatus(){
      if(!statusCd.isCancel()) statusCd = origStatusCd;
   }

但是,如果其他属性在本地更改,并且外部应用程序更新了状态,这将无济于事。Hibernate 从不更新单个属性,它总是一次完整的记录。

为了使其正常工作,您需要对版本或时间戳列进行乐观锁定。您的其他应用程序也需要使用这些列。请参阅http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html#d0e5844

如果您使用版本列,并且您的内部应用程序尝试更新记录,而外部应用程序已经更新了版本,您将获得 OptimisticLockException(或 StaleObjectStateException)。

于 2013-08-14T14:31:56.847 回答