站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Java 专题一个用java实现的数据库序列生成器

一个用java实现的数据库序列生成器

摘要: 一个用java实现的数据库序列生成器

</td> </tr> <tr> <td height="35" valign="top" class="ArticleTeitle"> <table width="681" border="0"> <tr> <td width="409">一个用java实现的数据库序列生成器

如果是集群等应用这个就不行了,只能在单应用的情况下使用。
对于每个序列键只需在第一次使用时查询数据库,后面的都将不需要查询。
有非常详细的注释,我就不多说了。


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;
</td> <td width="262">
</td></tr> </table> ?

/**
* 类Key是一个数据库主键生成器,用序列号的方式来产生数据库中需要的主键值。
*


* Key目前支持的数据库包括Oracle的所有版本、MySql的3.x以上的版本
* 以及所有支持max()函数的数据库,支持字段类型仅为数字类型的主键,对于字符及其它类型的主键尚不提供支持。
*


* 在使用时只需提供表名、字段名(主键)以及到数据库的JDBC连接,如果想要获得message表的id字段的下一个
* 主键值时:
*

 
* 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 + ",...)";
* //执行插入操作...
*


*
* @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 KeyException 如果表名或字段名不存在、访问数据库错误或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 KeyException 如果表名或字段名不存在或访问数据库错误时抛出
*/
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);
}
}

/**
* 用指定的"表.字段"形式的字符串获得key的下一个值,主键的值不得超过2147483647
* @param tableDotField "表.字段"形式的字符串,如:message.id
* @param conn JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
* @return key的下一个主键的int值
* @throws KeyException 如果表名或字段名不存在、访问数据库错误或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();
}

/**
* 用指定的"表.字段"形式的字符串获得key的下一个值,最大为9223372036854775807
* @param tableDotField "表.字段"形式的字符串,如:message.id
* @param conn JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
* @return key的下一个主键的int值
* @throws KeyException 如果表名或字段名不存在或访问数据库错误时抛出
*/
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 KeyException 如果表名或字段名不存在、访问数据库错误或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 KeyException 如果表名或字段名不存在或访问数据库错误时抛出
*/
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);
}
}

/**
* 用指定的"表.字段"形式的字符串获得key的当前值,主键的值不得超过2147483647
* @param tableDotField "表.字段"形式的字符串,如:message.id
* @param conn JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
* @return key的当前int值
* @throws KeyException 如果表名或字段名不存在、访问数据库错误或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();
}

/**
* 用指定的"表.字段"形式的字符串获得key的当前值,最大为9223372036854775807
* @param tableDotField "表.字段"形式的字符串,如:message.id
* @param conn JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
* @return key的当前int值
* @throws KeyException 如果表名或字段名不存在或访问数据库错误时抛出
*/
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();
}
}
}
</td> </tr> <tr>


↑返回目录
前一篇: 在AWT组件中显示Unicode字符
后一篇: 一个编写菜单的例子程序