ID生成器

       在一个关系数据库中,所有的数据都是存储在表里的,每一个表都有一个主键(Primary Key)。对大多数的用户输入数据来讲,主键需要由系统以序列号的方式产生(大多数),而不是由操作人员给出。

      某些关系数据库引擎提供某种序列键生成机制。如SQL Server允许每一个表内可以有一个自动编号列。Oracle提供Sequence对象,可以提供序列键值。

      主键:它的值用于惟一地标识表中的某一条记录

      但某些数据库引擎则没有相应的机制,如Sybase。这时就需要我们自己去生成主键序列号。通常的做法是使用一个表来存储所有的主键最大值。这个表包含两个列,一个列存放键名,另一个列存放键值.

      主键生成器的使用环境

       1.主键自动增长序列,这时需要一个主键生成器

       2.大数据量表中,查询主键最大值,我们需要一个主键生成器跟踪数据表中的主键状态,当需要查询数据表中的记录数时,只需要查询一下主键维护表就可以迅速得出结果.

       主键生成器的代码(Java)实现

/**
 * id生成器
 * @author Administrator
 *
 */
public class IdGenerator {

	/**
	 * 根据表名生成该表的序列
	 * @param tableName
	 * @return 返回生成的序列
	 */
	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);
		}
	} 

}

   上述代码中,需要注意的是,主键生成器的多线程问题使用了"for updat"悲观锁来解决.悲观锁是采用数据库机制实现的,数据被锁住之后其他用户将无法查看,直到锁释放,只有提交或回滚事务锁才会释放.for update语句只能放到select语句中,因为查询时把数据锁住才有意义.悲观锁的使用仅是将查询的一条数据锁住,而不是整个主键维护表.

 

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
客户端ID生成器是一种用于生成独一无二标识符的工具,该标识符用于标识和区分不同的客户端。在计算机系统和网络应用中,客户端ID通常用于识别和跟踪特定的用户或设备。 客户端ID生成器的作用是根据一定的规则和算法生成唯一的ID。这个ID可以是数字、字母、符号的组合,通常是一个字符串形式的值。生成的ID应该具备唯一性,并且不易被猜测或重复。这样可以有效地避免冲突和混淆,确保系统的正常运行和数据的准确性。 通常情况下,客户端ID生成器会采用一些特定的规则和方法来生成ID。例如,可以使用时间戳、随机数、设备信息等作为生成ID的依据,经过一定的计算和处理,生成一个唯一的标识符。生成的ID可以被存储在数据库或者其他数据结构中,用于后续的识别和验证。 客户端ID生成器在实际应用中有着广泛的用途。例如,在网络应用中,通过生成唯一的客户端ID可以实现用户行为的跟踪和记录,用于统计和分析用户的访问情况;在分布式系统中,通过生成唯一的客户端ID可以实现资源的分配和管理,用于确保每个客户端的正常运行。 总之,客户端ID生成器是一种用于生成独一无二标识符的工具,它具备唯一性、不易重复和不易猜测的特点。通过生成唯一的客户端ID,可以实现用户的识别和跟踪,确保系统的正常运行和数据的准确性。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值