在这里有个锁的概念:
锁:在静态方法上的锁属于类的锁
数据库中的锁悲观锁,一上来查询的时候就把那条记录锁住select * from t_table_id where table_name='t_client' for update;这样就可以对这个记录进行修改等,只有当事务提交或回滚事务时才会释放锁.这个锁不单是oracle中有的,其他数据库中也是有的
在java中:
synchronized 加入到成员方法上和 synchronized(this)两种写法含义是一样的,都是对对象加锁,不是对方法加锁
如果将synchronized加到静态方法上,是对类加锁,而不是对对象加锁,因为静态方法属于类
在数据库中:
可以使用数据库的悲观锁,例如:select value from t_table_id where table_name=? for update,悲观锁是采用数据库机制实现的,数据被锁住之后其他用户将无法查看,直
到锁释放,只有提交或回滚事务锁才会释放。for update 语句只能放到 select 语句中,因为查询时把数据锁住才有意义
ublic class IdGenerator {
/**
* 根据表名生成该表的序列
* @param tableName
* @return 返回生成的序列
*/
//public static synchronized int generate(String tableName) {
//public synchronized int generate(String tableName) {
//synchronized(this) {
public static int generate(String tableName) {
//使用数据库的悲观锁for update
String sql = "select value from t_table_id where table_name=? for update";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
int value = 0;
try {
conn = DbUtil.getConnection();
//开始事务
DbUtil.beginTransaction(conn);
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, tableName);
rs = pstmt.executeQuery();
if (!rs.next()) {
throw new RuntimeException();
}
value = rs.getInt("value");
value++; //自加
modifyValueField(conn, tableName, value);
//提交事务
DbUtil.commitTransaction(conn);
}catch(Exception e) {
e.printStackTrace();
//回滚事务
DbUtil.rollbackTransaction(conn);
throw new RuntimeException();
}finally {
DbUtil.close(rs);
DbUtil.close(pstmt);
DbUtil.resetConnection(conn); //重置Connection的状态
DbUtil.close(conn);
}
return value;
}
/**
* 根据表名更新序列字段的值
* @param conn
* @param tableName
* @param value
*/
private static void modifyValueField(Connection conn, String tableName, int value)
throws SQLException {
String sql = "update t_table_id set value=? where table_name=?";
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, value);
pstmt.setString(2, tableName);
pstmt.executeUpdate();
}finally {
DbUtil.close(pstmt);
}
}
public static void main(String[] args) {
int retValue = IdGenerator.generate("t_client");
System.out.println(retValue);
}
}