如果是集群等應(yīng)用這個(gè)就不行了,只能在單應(yīng)用的情況下使用 對(duì)于每個(gè)序列鍵只需在第一次使用時(shí)查詢數(shù)據(jù)庫(kù),后面的都將不需要查詢 有非常詳細(xì)的注釋,我就不多說(shuō)了
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>是一個(gè)數(shù)據(jù)庫(kù)主鍵生成器,用序列號(hào)的方式來(lái)產(chǎn)生數(shù)據(jù)庫(kù)中需要的主鍵值。 * <p> * <code>Key</code>目前支持的數(shù)據(jù)庫(kù)包括Oracle的所有版本、MySql的3.x以上的版本 * 以及所有支持max()函數(shù)的數(shù)據(jù)庫(kù),支持字段類型僅為數(shù)字類型的主鍵,對(duì)于字符及其它類型的主鍵尚不提供支持。 * <p> * 在使用時(shí)只需提供表名、字段名(主鍵)以及到數(shù)據(jù)庫(kù)的JDBC連接,如果想要獲得message表的id字段的下一個(gè) * 主鍵值時(shí): * <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 + ",...)"; * //執(zhí)行插入操作... * </pre></blockquote><p> * * @author 令少爺(shaoye@vip.sina.com) * @since magic 0.1 */ public final class Key {
/** * key的最大值,默認(rèn)為9223372036854775807,即long類型的最大值 */ private long max = 9223372036854775807L;
/** * key的最小值,默認(rèn)為1 * */ private long min = 1L;
/** * Key的唯一實(shí)例,通過(guò)getInstance()方法獲得 * */ private static Key keygen = new Key();
/** * KeyInfo類的實(shí)例列表,默認(rèn)容量為5個(gè) * */ private HashMap keyList = new HashMap(5); //keyInfo 列表
/** * 私有的默認(rèn)構(gòu)造方法,防止外部構(gòu)造類的實(shí)例 * */ private Key() { }
/** * 獲得Key的唯一實(shí)例 * */ public static Key getInstance() { return keygen; }
/** * 用指定的表和字段獲得key的下一個(gè)值,主鍵的值不得超過(guò)2147483647 * @param tableName 數(shù)據(jù)庫(kù)中的表名,表中必須有一個(gè)數(shù)字主鍵 * @param keyName 表(tableName)中的字段名 * @param connJDBC連接,如果欲獲得的key是第一次取值,則必須保證conn能連接到數(shù)據(jù)庫(kù) * @return key的下一個(gè)主鍵的int值 * @throws <code>KeyException</code>如果表名或字段名不存在、訪問(wèn)數(shù)據(jù)庫(kù)錯(cuò)誤或key的值大于2147483647時(shí)拋出 */ 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的下一個(gè)值,最大為9223372036854775807 * @param tableName 數(shù)據(jù)庫(kù)中的表名,表中必須有一個(gè)數(shù)字主鍵 * @param keyName 表(tableName)中的字段名 * @param connJDBC連接,如果欲獲得的key是第一次取值,則必須保證conn能連接到數(shù)據(jù)庫(kù) * @return key的下一個(gè)主鍵的long值 * @throws <code>KeyException</code>如果表名或字段名不存在或訪問(wèn)數(shù)據(jù)庫(kù)錯(cuò)誤時(shí)拋出 */ 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的下一個(gè)值,主鍵的值不得超過(guò)2147483647 * @param tableDotField"表.字段"形式的字符串,如:message.id * @param connJDBC連接,如果欲獲得的key是第一次取值,則必須保證conn能連接到數(shù)據(jù)庫(kù) * @return key的下一個(gè)主鍵的int值 * @throws <code>KeyException</code>如果表名或字段名不存在、訪問(wèn)數(shù)據(jù)庫(kù)錯(cuò)誤或key的值 * 大于2147483647時(shí)拋出 */ 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的下一個(gè)值,最大為9223372036854775807 * @param tableDotField"表.字段"形式的字符串,如:message.id * @param connJDBC連接,如果欲獲得的key是第一次取值,則必須保證conn能連接到數(shù)據(jù)庫(kù) * @return key的下一個(gè)主鍵的int值 * @throws <code>KeyException</code>如果表名或字段名不存在或訪問(wèn)數(shù)據(jù)庫(kù)錯(cuò)誤時(shí)拋出 */ 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的當(dāng)前值,主鍵的值不得超過(guò)2147483647 * @param tableName 數(shù)據(jù)庫(kù)中的表名,表中必須有一個(gè)數(shù)字主鍵 * @param keyName 表(tableName)中的字段名 * @param connJDBC連接,如果欲獲得的key是第一次取值,則必須保證conn能連接到數(shù)據(jù)庫(kù) * @return key的當(dāng)前int值 * @throws <code>KeyException</code>如果表名或字段名不存在、訪問(wèn)數(shù)據(jù)庫(kù)錯(cuò)誤或key的值大于2147483647時(shí)拋出 */ 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的當(dāng)前值,最大為9223372036854775807 * @param tableName 數(shù)據(jù)庫(kù)中的表名,表中必須有一個(gè)數(shù)字主鍵 * @param keyName 表(tableName)中的字段名 * @param connJDBC連接,如果欲獲得的key是第一次取值,則必須保證conn能連接到數(shù)據(jù)庫(kù) * @return key的當(dāng)前l(fā)ong值 * @throws <code>KeyException</code>如果表名或字段名不存在或訪問(wèn)數(shù)據(jù)庫(kù)錯(cuò)誤時(shí)拋出 */ 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的當(dāng)前值,主鍵的值不得超過(guò)2147483647 * @param tableDotField"表.字段"形式的字符串,如:message.id * @param connJDBC連接,如果欲獲得的key是第一次取值,則必須保證conn能連接到數(shù)據(jù)庫(kù) * @return key的當(dāng)前int值 * @throws <code>KeyException</code>如果表名或字段名不存在、訪問(wèn)數(shù)據(jù)庫(kù)錯(cuò)誤或key的值 * 大于2147483647時(shí)拋出 */ 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的當(dāng)前值,最大為9223372036854775807 * @param tableDotField"表.字段"形式的字符串,如:message.id * @param connJDBC連接,如果欲獲得的key是第一次取值,則必須保證conn能連接到數(shù)據(jù)庫(kù) * @return key的當(dāng)前int值 * @throws <code>KeyException</code>如果表名或字段名不存在或訪問(wèn)數(shù)據(jù)庫(kù)錯(cuò)誤時(shí)拋出 */ 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); } }
/** * 內(nèi)部類,用來(lái)存儲(chǔ)主鍵信息 * */ class KeyInfo { private long max = 9223372036854775807L; private long min = 1L; private long nextKey; private String tableName; private String keyName; private Connection conn = null; /** * keyInfo 對(duì)象初始化 */ 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; } /** * 取當(dāng)前鍵值 */ synchronized int getCurrentKey() { return (new Long(nextKey)).intValue(); } /** * 取當(dāng)前鍵值 */ synchronized long getCurrentKeyLong() { return nextKey; } /** * 從數(shù)據(jù)庫(kù)中取當(dāng)前最大值 */ 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(); } } }
|