我正在尝试编写一个可在多台服务器上运行但共享一个数据库进行金融交易的Web应用程序。
简单来说,我想将资金从帐户A转移到B.但可能有多个请求从同一帐户转帐。
余额永远不会是负数,因此我决定使用SELECT FOR UPDATE获取余额来锁定行。
我正在使用JDBI连接数据库:http://jdbi.org/
代码流程如下:
控制器:
DBI dbi = new DBI(datasource);
.....
getAccountBalance();
....
transfer()
这是DOA部分
public int getAccountBalance(String id) {
Handle h = dbi.open();
try{
return h.createQuery("SELECT balance FROM accounts " +
" WHERE id=:id FOR UPDATE;")
.bind("id", id)
.mapTo(Integer.class)
.first();
} finally {
h.close();
}
}
DAO返回余额,我进行余额检查以确定是否可以进行转帐,然后再调用另一种方法来执行转账。
public void transfer(String fromAccountId, String toAccountId, int transferAmount) {
Handle h = dbi.open();
try{
h.begin();
h.createStatement("UPDATE accounts SET balance = balance - :transferAmount WHERE id = :fromAccountId")
.bind("fromAccountId", fromAccountId)
.bind("transferAmount", transferAmount)
.execute();
h.createStatement("UPDATE accounts SET balance = balance + :transferAmount WHERE id = :toAccountId")
.bind("toAccountId", toAccountId)
.bind("transferAmount", transferAmount)
.execute();
h.commit();
} finally {
h.close();
}
}
我的问题是,如果我关闭getAccountBalance()
中的句柄会释放它所选行的锁吗?如果是这样的话,我该怎么办?我是DBI的新手。谢谢
答案 0 :(得分:3)
它实际上是在h.close()
h.commit()
之前发布的。行锁不会超出提交范围。
如果你需要过去提交的锁,你可以使用咨询锁,但它们有点尴尬,而不是我推荐的类似这样的东西。
否则请阅读pessimistic vs optimistic locking。另请参阅Optimistic vs. Pessimistic locking。