我先把问题描述一下,我想实现用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 这样的功能。
还请高手指点迷津。。。谢谢了!