现在有如下的业务场景:
数据库里边只有id,time2个字段,数据库里边id是自增的。现在需要对id进行一次更新之后,再去进行查询,
以期获得最新的id,并返回给业务方。
public IDGenerateEntityDb execSql(final String time) throws Exception {
DaoWrapper wrapper = BaseDaoWrapperFactory.getDaoWrapper();
final String sql = "replace into tbl (time) values(" + time + ")";
IDGenerateEntityDb db = new IDGenerateEntityDb();
final Lock lock = new ReentrantLock();
lock.lock();
Long id = (Long) wrapper.execInsert(sql, new IPreparedStatementHandler() {
public Object exec(PreparedStatement paramPreparedStatement) throws SQLException {
int s = paramPreparedStatement.executeUpdate(sql);// 返回的是执行的条数
Long idLong = null;
try {
if (s == 1 || s == 2) { // 表明执行成功
ResultSet set = paramPreparedStatement.executeQuery(" SELECT * from tbl where time= " + time);
while (set.next()) {
idLong = set.getLong("id");
System.out.println(idLong);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return idLong;
}
});
db.setId(id);
return db;
}
用这种方式的时候,拿到的结果就会有重复数据,但是将ReentrantLock改为Synchronized后拿到的结果就正常了,这是什么原因呢。是不是加锁的额方式不对呢?
finally代码块中执行lock.unlock(),此时释放了锁,但在释放锁之前,已经有返回值了。你将return idLong;放到lock.unlock();之后就可以了。
上述代码,也不可以。如果插入语句之后,关闭连接,然后再执行是可以的。相信说到这里,你已经知道为什么了。。。