如果是集群等应用这个就不行了,只能在单应用的情况下使用
对于每个序列键只需在第一次使用时查询数据库,后面的都将不需要查询
有非常详细的注释,我就不多说了
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("keys 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("keys 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("keys 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("keys 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("cant connect database!");
}
try {
rs = pstmt.executequery();
}
catch (sqlexception sqle) {
if (pstmt != null)
pstmt.close();
throw new keyexception(
"" + keyname + " or " + tablename + " isnt 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();
}
}
}
