十万火急!!!!!大家帮帮忙啊。。


我先把问题描述一下,我想实现用JDBC实现类似hibernate的悲观锁。


//点击"修改"链接后调用get方法,将记录查询出来转向edit.jsp页面,让用户进行修改
public BookDTO get(int id) {
BookDTO book = null;
PreparedStatement psmt = null;
try {
conn.setAutoCommit(false);
psmt = conn.prepareStatement(SQL_GET);
psmt.setInt(1, id);
ResultSet rs = psmt.executeQuery();
if (rs.next()) {
book = new BookDTO();
book.setBid(rs.getInt(1));
book.setBookName(rs.getString(2));
book.setPrice(rs.getFloat(3));
book.setAuthor(rs.getString(4));
book.setPublisher(rs.getString(5));
book.setIsbn(rs.getString(6));
book.setCid(rs.getInt(7));
book.setDatastyle(rs.getString(8));
}
conn.commit();
conn.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (psmt != null)
psmt.close();
} catch (SQLException e) {
e.printStackTrace();
}

}
return book;
}


//执行修改,点击提交后调用的方法
public boolean update(BookDTO dto) {

try {
psmt = conn.prepareStatement(SQL_UPDATE);
psmt.setString(1, dto.getBookName());
psmt.setFloat(2, dto.getPrice());
psmt.setString(3, dto.getIsbn());
psmt.setString(4, dto.getAuthor());
psmt.setString(5, dto.getPublisher());
psmt.setInt(6, dto.getCid());
psmt.setString(7, dto.getDatastyle());
psmt.setInt(8, dto.getBid());
psmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (psmt != null)
psmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}

return false;
}


现在我想实现的功能是:

当用户A调用get方法后,在A提交修改信息之前,B用户调用get方法直接返回"异常信息".
SQL_GET 我是这样写的: SELECT * FROM MVC_BOOK WHERE id=? FOR UPDATE NOWAIT 将其用行锁锁住.
但是我在测试的时候,结果却是A用户调用get后,在A用户执行update方法前,B用户调用get方法却能正常执行完该方法,没有转向异常!


上面get方法中:
conn.setAutoCommit(false);

...

conn.commit();
conn.setAutoCommit(true);

--如果不显示去写commit,A用户调用到get方法执行到ResultSet rs = psmt.executeQuery();会报异常!所以在这里加上了,但加上后我又想在A用户调用get方法的时候先不commit,等A调用update后再提交,于是我就只加了conn.setAutoCommit(false);这一句,但是还是不行!


请问要在get方法中怎么加代码来实现我说的上述功能呢?也就是悲观锁的实现!谢谢~在线等


我分析出的问题是:当点击修改连接,调用后台get方法的时候,执行完sql,get方法执行完毕,就把对该条记录的锁释放了,等显示到页面,其他的用户当然可以对该条记录进行修改了,我想怎么能扩大事务的边界,类似spring提供的OpenSessionInview 这样的功能。

还请高手指点迷津。。。谢谢了!

悲观锁是使用数据库的锁机制,对于连接参数还需要进行特别设置,不同数据库缺省的事务隔离级别不一样,还要进行设置各种参数,相当繁琐。

而且悲观锁性能极其差,几乎无法并发写。

建议你不必重新发明轮子,除非你真是闲得慌,不过看来十万火急在线等,你的时间也不是那么充裕,为什么做这种让自己纠结的事情呢?呵呵。

2011年05月09日 13:31 "@shanghuijie"的内容
当点击修改连接,调用后台get方法的时候,执行完sql,get方法执行完毕,就把对该条记录的锁释放了,等显示到页面,其他的用户当然可以对该条记录进行修改了,我想怎么能扩大事务的边界,类似spring提供的OpenSessionInview ...

你这个需要悲观离线锁,需要自己自己手动控制一把锁,性能差异。
spring提供的OpenSessionInview的事务边界也短,在方法的前后。
现在项目中就一个模块需要这样实现,其他的地方不考虑。我的意思是现在没法实现数据库这样的锁机制。昨天我研究了一下,如果后台调用get方法,设置connection.setAutocommit(false) 完之后,不提交事务,此时其他的就不能对锁住的这条记录进行修改了。
但是我点击修改保存之后,拿不到以前的connection了,也就没法把这条记录提交,这条记录,谁都改不了了。
现在关键是我怎么找到对应的connection,把他提交然后关闭了呢?

还请bang给指点指点。谢谢了。