<%@ page contentType="text/html; charset=gb2312"%> 一个用java实现的数据库序列生成器
网站公告:   ◆北天JAVA技术网热情为java爱好者服务,本网内容包括JAVA(JSP、servlet、EJB、webservice、j2ee、javabean、应用服务器、JavaScript),数据库(MYSQL、SQL Server、Sybase、Oracle、DB2、数据库综合知识),设计研究(设计模式、Struts、Spring、Hibernate、设计框架、设计综合知识),WEB2.0新技术(主要介绍AJAX),以及各种技术的入门、实例、例子等等,欢迎各位多来坐坐!◆  诚邀各位JAVA爱好者加盟!◆  本网站内容丰富,更新快,保证每周20篇以上!  
加入收藏
设为首页
联系站长
承接项目
  相关资源:网站首页 | 免费培训学院 | 技术论坛 | JAVA聊天室 | 作家专栏 | 开发工具 | 认证考试 | 会员俱乐部
  JAVA技术初学者园地 | jsp与servlet | javascript | Java源代码 | EJB | web service | 应用服务器 | JAVA综合知识
  设计研究设计模式 | 设计框架 | Struts | Spring | Hibernate | 开源项目 | 面向对象设计 | 设计综合知识
  数 据 库MYSQL | SQL Server | Sybase | Oracle | DB2 | Informix | Access | 数据库综合知识
  其他资源:AJAX新技术 | 网站开发 | ERP软件 | OA办公软件 | 商业智能BI | 开发综合知识 | 承接项目 | 项目试用

 
 
一个用java实现的数据库序列生成器
     发布者: 发布时间:2006-07-25
如果是集群等应用这个就不行了,只能在单应用的情况下使用
对于每个序列键只需在第一次使用时查询数据库,后面的都将不需要查询
有非常详细的注释,我就不多说了


package org.shaoye.common.sql;

import java.util.HashMap;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
* 类<code>Key</code>是一个数据库主键生成器,用序列号的方式来产生数据库中需要的主键值。
* <p>
* <code>Key</code>目前支持的数据库包括Oracle的所有版本、MySql的3.x以上的版本
* 以及所有支持max()函数的数据库,支持字段类型仅为数字类型的主键,对于字符及其它类型的主键尚不提供支持。
* <p>
* 在使用时只需提供表名、字段名(主键)以及到数据库的JDBC连接,如果想要获得message表的id字段的下一个
* 主键值时:
* <p><blockquote><pre>
*     java.sql.Connection conn = ...;
*     org.shaoye.common.sql.Key key = org.shaoye.common.sql.Key.getInstance();
*     int keyValue = key.getNextKey("message", "id", conn);
*     String sql = "insert into message (id,...) values (" + keyValue + ",...)";
*     //执行插入操作...
* </pre></blockquote><p>
*
* @author 令少爷(shaoye@vip.sina.com)
* @since magic 0.1
*/
public final class Key {

/**
  * key的最大值,默认为9223372036854775807,即long类型的最大值
  */
private long max = 9223372036854775807L;

/**
  * key的最小值,默认为1
  * */
private long min = 1L;

/**
  * Key的唯一实例,通过getInstance()方法获得
  * */
private static Key keygen = new Key();

/**
  * KeyInfo类的实例列表,默认容量为5个
  * */
private HashMap keyList = new HashMap(5); //keyInfo 列表

/**
  * 私有的默认构造方法,防止外部构造类的实例
  * */
private Key() {
}

/**
  * 获得Key的唯一实例
  * */
public static Key getInstance() {
  return keygen;
}

/**
  * 用指定的表和字段获得key的下一个值,主键的值不得超过2147483647
  * @param tableName   数据库中的表名,表中必须有一个数字主键
  * @param keyName   表(tableName)中的字段名
  * @param conn    JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
  * @return key的下一个主键的int值
  * @throws <code>KeyException</code>  如果表名或字段名不存在、访问数据库错误或key的值大于2147483647时抛出
  */
public int getNextKey(String tableName, String keyName, Connection conn) throws KeyException {
  long value = getNextKeyLong(tableName, keyName, conn);
  if (value > 2147483647L) {
   throw new KeyException("Key''s value too big,please call getNextKeyLong method!");
  }
  return (new Long(value)).intValue();
}

/**
  * 用指定的表和字段获得key的下一个值,最大为9223372036854775807
  * @param tableName   数据库中的表名,表中必须有一个数字主键
  * @param keyName   表(tableName)中的字段名
  * @param conn    JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
  * @return key的下一个主键的long值
  * @throws <code>KeyException</code>  如果表名或字段名不存在或访问数据库错误时抛出
  */
public long getNextKeyLong(String tableName, String keyName, Connection conn)
  throws KeyException {
  KeyInfo keyinfo;
  String item = tableName + "." + keyName;
  try {
   if (keyList.containsKey(item)) {
    keyinfo = (KeyInfo) keyList.get(item);
   }
   else {
    keyinfo = new KeyInfo(tableName, keyName, conn);
    keyList.put(item, keyinfo);
   }
   return keyinfo.getNextKey();
  }
  catch (SQLException sqle) {
   throw new KeyException(sqle);
  }
}

/**
  * 用指定的"表<code>.</code>字段"形式的字符串获得key的下一个值,主键的值不得超过2147483647
  * @param tableDotField  "表.字段"形式的字符串,如:message.id
  * @param conn    JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
  * @return key的下一个主键的int值
  * @throws <code>KeyException</code>  如果表名或字段名不存在、访问数据库错误或key的值
  * 大于2147483647时抛出
  */
public int getNextKey(String tableDotField, Connection conn) throws KeyException {
  long value = getNextKeyLong(tableDotField, conn);
  if (value > 2147483647L) {
   throw new KeyException("Key''s value too big,please call getNextKeyLong method!");
  }
  return (new Long(value)).intValue();
}

/**
  * 用指定的"表<code>.</code>字段"形式的字符串获得key的下一个值,最大为9223372036854775807
  * @param tableDotField  "表.字段"形式的字符串,如:message.id
  * @param conn    JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
  * @return key的下一个主键的int值
  * @throws <code>KeyException</code>  如果表名或字段名不存在或访问数据库错误时抛出
  */
public long getNextKeyLong(String tableDotField, Connection conn) throws KeyException {
  int dot_index = tableDotField.indexOf(".");
  if (tableDotField.indexOf(".") < 1) {
   throw new KeyException("Unknown Key ''" + tableDotField + "''!");
  }
  String tab = tableDotField.substring(0, dot_index);
  String key = tableDotField.substring(dot_index);
  return getNextKeyLong(tab, key, conn);
}

/**
  * 用指定的表和字段获得key的当前值,主键的值不得超过2147483647
  * @param tableName   数据库中的表名,表中必须有一个数字主键
  * @param keyName   表(tableName)中的字段名
  * @param conn    JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
  * @return key的当前int值
  * @throws <code>KeyException</code>  如果表名或字段名不存在、访问数据库错误或key的值大于2147483647时抛出
  */
public int getCurrentKey(String tableName, String keyName, Connection conn)
  throws KeyException {
  long value = getCurrentKeyLong(tableName, keyName, conn);
  if (value > 2147483647L) {
   throw new KeyException("Key''s value too big,please call getCurrentKeyLong method!");
  }
  return (new Long(value)).intValue();
}

/**
  * 用指定的表和字段获得key的当前值,最大为9223372036854775807
  * @param tableName   数据库中的表名,表中必须有一个数字主键
  * @param keyName   表(tableName)中的字段名
  * @param conn    JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
  * @return key的当前long值
  * @throws <code>KeyException</code>  如果表名或字段名不存在或访问数据库错误时抛出
  */
public long getCurrentKeyLong(String tableName, String keyName, Connection conn)
  throws KeyException {
  KeyInfo keyinfo;
  String item = tableName + "." + keyName;
  try {
   synchronized (keyList) {
    if (keyList.containsKey(item)) {
     keyinfo = (KeyInfo) keyList.get(item);
    }
    else {
     keyinfo = new KeyInfo(tableName, keyName, conn);
     keyList.put(item, keyinfo);
    }
   }
   return keyinfo.getCurrentKey();
  }
  catch (SQLException sqle) {
   throw new KeyException(sqle);
  }
}

/**
  * 用指定的"表<code>.</code>字段"形式的字符串获得key的当前值,主键的值不得超过2147483647
  * @param tableDotField  "表.字段"形式的字符串,如:message.id
  * @param conn    JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
  * @return key的当前int值
  * @throws <code>KeyException</code>  如果表名或字段名不存在、访问数据库错误或key的值
  * 大于2147483647时抛出
  */
public int getCurrentKey(String tableDotField, Connection conn) throws KeyException {
  long value = getCurrentKeyLong(tableDotField, conn);
  if (value > 2147483647L) {
   throw new KeyException("Key''s value too big,please call getNextKeyLong method!");
  }
  return (new Long(value)).intValue();
}

/**
  * 用指定的"表<code>.</code>字段"形式的字符串获得key的当前值,最大为9223372036854775807
  * @param tableDotField  "表.字段"形式的字符串,如:message.id
  * @param conn    JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
  * @return key的当前int值
  * @throws <code>KeyException</code>  如果表名或字段名不存在或访问数据库错误时抛出
  */
public long getCurrentKeyLong(String tableDotField, Connection conn) throws KeyException {
  int dot_index = tableDotField.indexOf(".");
  if (tableDotField.indexOf(".") < 1) {
   throw new KeyException("Unknown Key ''" + tableDotField + "''!");
  }
  String tab = tableDotField.substring(0, dot_index);
  String key = tableDotField.substring(dot_index);
  return getCurrentKeyLong(tab, key, conn);
}
}


/**
* 内部类,用来存储主键信息
* */
class KeyInfo {
private long max = 9223372036854775807L;
private long min = 1L;
private long nextKey;
private String tableName;
private String keyName;
private Connection conn = null;
/**
  * keyInfo 对象初始化
  */
KeyInfo(String tableName, String keyName, Connection _conn) throws SQLException {
  this.tableName = tableName;
  this.keyName = keyName;
  this.conn = _conn;
  retrieveFromDB();
}
int getMax() {
  return (new Long(max)).intValue();
}
long getMaxLong() {
  return max;
}
int getMin() {
  return (new Long(min)).intValue();
}
long getMinLong() {
  return min;
}
/**
  * 取下一键值
  */
int getNextKey() {
  return (new Long(getNextKeyLong())).intValue();
}
/**
  * 取下一键值
  */
synchronized long getNextKeyLong() {
  nextKey++;
  return nextKey;
}
/**
  * 取当前键值
  */
synchronized int getCurrentKey() {
  return (new Long(nextKey)).intValue();
}
/**
  * 取当前键值
  */
synchronized long getCurrentKeyLong() {
  return nextKey;
}
/**
  * 从数据库中取当前最大值
  */
void retrieveFromDB() throws SQLException {
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  int keyFromDB = 0;
  String sql = "select max(" + keyName + ") from " + tableName;
  try {
   pstmt = conn.prepareStatement(sql);
  }
  catch (Exception ex) {
   throw new KeyException("Can''t connect DataBase!");
  }
  try {
   rs = pstmt.executeQuery();
  }
  catch (SQLException sqle) {
   if (pstmt != null)
    pstmt.close();
   throw new KeyException(
    "''" + keyName + "'' or ''" + tableName + "'' isn''t exist in DataBase!",
    sqle);
  }
  try {
   if (rs.next()) {
    nextKey = rs.getLong(1);
    if (nextKey < min) {
     nextKey = min;
    }
   }
   else {
    nextKey = min;
   }
  }
  catch (SQLException sqle) {
   throw (sqle);
  }
  finally {
   if (rs != null)
    rs.close();
   if (pstmt != null)
    pstmt.close();
  }
}
}
(转载文章请保留出处:北天JAVA技术网(www.java114.com))
 
更多精彩文章:
利用JDK1.4中的Templates实现xslt转换的缓存
一个操作String的javabean
给大家一个进行IO操作的JAVABEAN
给大家一个在SERVER端执行可执行程序的JAVABEAN
正确地封装Java类
利用Oracle自带的连接缓冲类的一个例子
 
        
标 题:   
内 容:   
 
                                  
 
免责声明:该文章由网友发表,如果对您造成侵权,请联系站长

首页 - 承接项目 - 网站地图 - 联系我们 -
版权所有北天JAVA技术工作室 ICP证号:粤ICP备06079815号