我的方案是我有两个不同的API更新数据库表,一个我们将调用内部,另一个外部调用,其中一个是使用陈旧数据覆盖值。
通过Hibernate更新的数据当时在应用程序的内存中。如果外部源在内部应用程序中仍然在内存中时更新列(statusCd),则在内部应用程序中保存它的那一分钟,该值将被过时数据覆盖。
现在我意识到还有很多方法可以解决这个问题,但是我们已经确定将此对象的Hibernate代码修复限制为风险最小,只要有可能通过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;
}
}
感谢您的时间,
亚历
答案 0 :(得分: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)。