【发布时间】:2014-08-20 04:25:36
【问题描述】:
编辑:
事实证明,在这种情况下,因为我使用的是“版本”注释,所以我使用的是乐观锁定,而不是悲观锁定。
如果我删除版本并因此禁用乐观锁定。悲观锁定接管并且性能显着下降。
所以我想我必须忍受乐观锁定和偶尔的异常。有没有更好的解决方案?
原文:
我目前通过 ajp 在 apache 2.2 负载均衡器中有多个 tomcat 实例。后端系统处于休眠状态。系统为多个用户和请求提供服务,对于请求,它会从用户的帐户中扣除一个信用。
我使用 hibernate 的悲观锁定来管理信用扣除。
我不时在日志中的用户帐户对象上收到以下信息:
代码
private boolean decUserAccountQuota(UserAccount userAccount, int creditDec) {
if(userAccount.getBalance() <1) return false;
String userName = userAccount.getUsername();
Manager manager = getManager(userName);
try{
manager.beginTransaction();
manager.refresh(userAccount, LockMode.UPGRADE); //this uses pessimistic locking, this calls sessionFactory.getCurrentSession().refresh();
userAccount.setBalance(userAccount.getBalance()-creditDec);
manager.commitTransaction(); //this causes the Exception
}catch(Exception exp){
exp.printStackTrace();
manager.rollbackTransaction();
return false;
}finally{
manager.closeSession();
}
return true;
}
问题:
- 如何防止此异常发生。这里发生了什么 是多个线程尝试更新同一个实体,一个线程 成功,因此,当下一个线程去提交数据时,它 看到它已经被修改并最终抛出 陈旧对象状态异常。但如果我已经在使用悲观 锁了,怎么还会出现异常?
- 在性能和完整性方面是否有更好的方法 管理用户帐户信用系统?
【问题讨论】:
-
从您的描述看来您实际上是在使用乐观锁定? docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch05.html 描述了差异。
-
@Gustav Grusell:请看更新
-
userAccount中是否有<version>映射到注释为@Version的字段上?如果是,hibernate 将在事务之间进行乐观锁定。 -
@Serge Ballesta:我应该删除版本和乐观锁定吗?
-
无论如何,您的异常很奇怪,因为在单个事务中您执行选择、修改和更新,这应该始终有效。
Manager类是什么?