如何获得自增序列号的下一个ID

cn2k8 2005-02-24 10:27:31
如题
...全文
745 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
owenchwz 2005-02-26
  • 打赏
  • 举报
回复
建议尽量不要(甚至反对)用自动递增列,在数据库移植时会出现诸多问题,用整型列替换自动递增列,我的做法是设计一个KeyGernator单例模式类进行表自动递增列管理,缺点是不能多个系统同时对一个数据库进行操作,代码如下:

/**
* @author OwenChan 2004-09-14
*
* 表INT类型键值生成类,其方法有getKeyFromTable(tablName)
* 与getKeyFromTable(tableName, fieldName),每调用一次生成一个新键值。
*
*/
public class DEKeyGenerator {

static Log log = LogFactory.getLog(DEKeyGenerator.class);

/**
* 键值保存容器,单例模式
*/
private final static HashMap keyContainer = new HashMap();

private static DESQL theSQL = new DESQL();

/**
* 取得指定表的整数键值,默认字段名是“id"
* @param tableName表名
* @return 指定表的最新键值
*/
public static int getKeyFromTable(String tableName) {
return getKeyFromTable(tableName, "id");
}

/**
* 获取表的键值(必须是int类型)
* @param tableName 表名
* @param keyFieldName 键值对应的字段名,默认值是"id".
* @return 返回表键值的最新值
*/
public static synchronized int getKeyFromTable(
String tableName,
String keyFieldName) {
//如果不指定表名则返回-1。
if (tableName == null || tableName.equals(""))
return -1;
int iResult = 1;
if (theSQL == null)
theSQL = new DESQL();
if (keyFieldName == null || keyFieldName.trim().equals(""))
keyFieldName = "id";
String key = tableName + ":" + keyFieldName;
if (!keyContainer.containsKey(key)) {
StringBuffer sb = new StringBuffer();
sb.append("select max(");
sb.append(keyFieldName);
sb.append(") maxid from ");
sb.append(tableName);
log.debug(sb.toString());
DynaBean bean = theSQL.getOneBean(sb.toString());
if (bean != null) {
Integer res = (Integer) bean.get("maxid");
if (res != null)
iResult = res.intValue() + 1;
}
keyContainer.put(key, new Integer(iResult));
} else {
Integer I = (Integer) keyContainer.get(key);
iResult = I.intValue() + 1;
keyContainer.put(key, new Integer(iResult));
}

return iResult;
}

}
cutelion 2005-02-26
  • 打赏
  • 举报
回复
dongcenphoenix 2005-02-26
  • 打赏
  • 举报
回复
mark
awaysrain 2005-02-26
  • 打赏
  • 举报
回复
用java在代码里+1的方法不好,如果出现并发访问的话就会有问题,还是依靠数据库机制比较好,Oracle用sequence
lhj 2005-02-26
  • 打赏
  • 举报
回复
在java里面有不好的地方,比如我的java程序要在2个以上的web服务器上跑的话,这个java的i++在2台机器上同步。还是比较麻烦的。
enjoy330 2005-02-24
  • 打赏
  • 举报
回复
用存储过程
108041217 2005-02-24
  • 打赏
  • 举报
回复
i++,哈哈,這就是java.數據庫就是your_sequence.nextval,用oralce 和postgres都是.
cn2k8 2005-02-24
  • 打赏
  • 举报
回复
在java类里面没有什么可以解决的方法吗
liqian008 2005-02-24
  • 打赏
  • 举报
回复
只会用oracle的... 同意 lhj(努力加油)
lhj 2005-02-24
  • 打赏
  • 举报
回复
如果是Oracle则用sequence

your_sequence.nextval
DaveyKing 2005-02-24
  • 打赏
  • 举报
回复
MSSQL:IDENT_CURRENT('table_name')
public synchronized String nextId() { long timestamp = timeGen(); //获取当前毫秒数 //如果服务器时间有问题(时钟后退) 报错。 if (timestamp < lastTimestamp) { throw new RuntimeException(String.format( "Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } //如果上次生成时间和当前时间相同,在同一毫秒内 if (lastTimestamp == timestamp) { //sequence自增,因为sequence只有12bit,所以和sequenceMask相与一下,去掉高位 sequence = (sequence + 1) & sequenceMask; //判断是否溢出,也就是每毫秒内超过4095,当为4096时,与sequenceMask相与,sequence就等于0 if (sequence == 0) { timestamp = tilNextMillis(lastTimestamp); //自旋等待到下一毫秒 } } else { sequence = 0L; //如果和上次生成时间不同,重置sequence,就是下一毫秒开始,sequence计数重新从0开始累加 } lastTimestamp = timestamp; long suffix = (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence; String datePrefix = DateFormatUtils.format(timestamp, "yyyyMMddHHMMssSSS"); return datePrefix + suffix; } protected long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } protected long timeGen() { return System.currentTimeMillis(); } private byte getLastIP(){ byte lastip = 0; try{ InetAddress ip = InetAddress.getLocalHost(); byte[] ipByte = ip.getAddress(); lastip = ipByte[ipByte.length - 1]; } catch (UnknownHostException e) { e.printStackTrace(); } return lastip; }

81,094

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧