注册
 找回密码
 注册
江西广告网
查看: 425|回复: 0
打印 上一主题 下一主题

Java实现的Sequence工具

[复制链接]

该用户从未签到

1
跳转到指定楼层
发表于 2009-3-17 08:14:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册

x
Sequence是数据库应用中很重要的一个特性,可是有些数据库没有这个特性,比如很流行的开源数据库MySQL就没有Sequence,利用自增主键感觉很不爽,每个表的ID都要设置,通用性也不好。因此考虑为这些不支持Sequence的数据做一个Sequence工具。自动为整个系统提供主键生成策略。 下面是一个Sequence实现,以数据库MySQL为平台。源代码如下: 一、Sequence工具类 package sequence; import java.util.HashMap; import java.util.Map; import java.sql.SQLException; /** * Created by IntelliJ IDEA.<br> * <b>User</b>: leizhimin<br> * <b>Date</b>: 2008-4-2 15:21:30<br> * <b>Note</b>: Java实现的Sequence工具 */ public class SequenceUtils { private static SequenceUtils _instance = new SequenceUtils(); private Map<String, KeyInfo> keyMap = new HashMap<String, KeyInfo>(20); //Sequence载体容器 private static final int POOL_SIZE = 10; //Sequence值缓存大小 /** * 禁止外部实例化 */ private SequenceUtils() { } /** * 获取SequenceUtils的单例对象 * @return SequenceUtils的单例对象 */ public static SequenceUtils getInstance() { return _instance; } /** * 获取下一个Sequence键值 * @param keyName Sequence名称 * @return 下一个Sequence键值 */ public synchronized long getNextKeyValue(String keyName) { KeyInfo keyInfo = null; Long keyObject = null; try { if (keyMap.containsKey(keyName)) { keyInfo = keyMap.get(keyName); } else { keyInfo = new KeyInfo(keyName, POOL_SIZE); keyMap.put(keyName, keyInfo); } keyObject = keyInfo.getNextKey(); } catch (SQLException e) { e.printStackTrace(); } return keyObject; } } [1] [2] [3] [4] [5] 二、Sequence载体 package sequence; import java.sql.*; /** * Created by IntelliJ IDEA.<br> * <b>User</b>: leizhimin<br> * <b>Date</b>: 2008-4-2 15:24:52<br> * <b>Note</b>: Sequence载体 */ public class KeyInfo { private long maxKey; //当前Sequence载体的最大值 private long minKey; //当前Sequence载体的最小值 private long nextKey; //下一个Sequence值 private int poolSize; //Sequence值缓存大小 private String keyName; //Sequence的名称 private static final String sql_update = "UPDATE KEYTABLE SET KEYVALUE = KEYVALUE ? WHERE KEYNAME = ?"; private static final String sql_query = "SELECT KEYVALUE FROM KEYTABLE WHERE KEYNAME = ?"; public KeyInfo(String keyName, int poolSize) throws SQLException { this.poolSize = poolSize; this.keyName = keyName; retrieveFromDB(); } public String getKeyName() { return keyName; } public long getMaxKey() { return maxKey; } public long getMinKey() { return minKey; } public int getPoolSize() { return poolSize; } /** * 获取下一个Sequence值 * * @return 下一个Sequence值 * @throws SQLException */ public synchronized long getNextKey() throws SQLException { if (nextKey > maxKey) { retrieveFromDB(); } return nextKey ; } /** * 执行Sequence表信息初始化和更新工作 * * @throws SQLException */ private void retrieveFromDB() throws SQLException { System.out.println(""); Connection conn = DBUtils.makeConnection(); //查询数据库 PreparedStatement pstmt_query = conn.prepareStatement(sql_query); pstmt_query.setString(1, keyName); ResultSet rs = pstmt_query.executeQuery(); if (rs.next()) { maxKey = rs.getLong(1) poolSize; minKey = maxKey - poolSize 1; nextKey = minKey; rs.close(); pstmt_query.close(); } else { System.out.println("执行Sequence数据库初始化工作!"); String init_sql = "INSERT INTO KEYTABLE(KEYNAME,KEYVALUE) VALUES('" keyName "',10000 " poolSize ")"; Statement stmt = conn.createStatement(); stmt.executeUpdate(init_sql); maxKey = 10000 poolSize; minKey = maxKey - poolSize 1; nextKey = minKey; stmt.close(); return; } //更新数据库 conn.setAutoCommit(false); System.out.println("更新Sequence最大值!"); PreparedStatement pstmt_up = conn.prepareStatement(sql_update); pstmt_up.setLong(1, poolSize); pstmt_up.setString(2, keyName); pstmt_up.executeUpdate(); pstmt_up.close(); conn.commit(); rs.close(); pstmt_query.close(); conn.close(); } } 上一页 [1] [2] [3] [4] [5] 三、简单的数据库连接工具 package sequence; import java.sql.*; /** * 简单的数据连接工具 * File: DBUtils.java * User: leizhimin * Date: 2008-3-18 15:19:12 */ public class DBUtils { public static final String url = "jdbc:mysql://127.0.0.1:3306/testdb"; public static final String username = "root"; public static final String password = "leizhimin"; public static final String driverClassName = "com.mysql.jdbc.Driver"; /** * 获取数据库连接Connection * * @return 数据库连接Connection */ public static Connection makeConnection() { Connection conn = null; try { Class.forName(driverClassName); } catch (ClassNotFoundException e) { e.printStackTrace(); } try { conn = DriverManager.getConnection(url, username, password); } catch (SQLException e) { e.printStackTrace(); } return conn; } public static void main(String args[]) { testConnection(); } /** * 测试连接方法 */ public static void testConnection() { Connection conn = makeConnection(); try { Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM mysql.user"); while (rs.next()) { String s1 = rs.getString(1); String s2 = rs.getString(2); System.out.println(s1 "\t" s2); } rs.close(); stmt.close(); } catch (SQLException e) { e.printStackTrace(); } finally { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } 上一页 [1] [2] [3] [4] [5] 四、测试类(客户端) package sequence; /** * Created by IntelliJ IDEA. * User: leizhimin * Date: 2008-4-2 15:31:30 * Company: LavaSoft(http://lavasoft.blog.51cto.com) * Sequence测试(客户端) */ public class TestSequence { /** * 测试入口 * @param args */ public static void main(String args[]) { test(); } /** * 测试Sequence方法 */ public static void test() { System.out.println("----------test()----------"); for (int i = 0; i < 20; i ) { long x = SequenceUtils.getInstance().getNextKeyValue("sdaf"); System.out.println(x); } } } 五、Sequence表的代码(for MySQL5) -- SQL for MySQL5 -- http://lavasoft.blog.51cto.com -- 2008年4月3日 -- 创建数据库testdb create database if not exists testdb character set gbk collate gbk_chinese_ci; -- 创建Sequence表 DROP TABLE IF EXISTS keytable; CREATE TABLE keytable ( KEYNAME varchar(24) NOT NULL COMMENT 'Sequence名称', KEYVALUE bigint(20) DEFAULT '10000' COMMENT 'Sequence最大值', PRIMARY KEY (KEYNAME) ) ENGINE=MyISAM DEFAULT CHARSET=gbk; 数据库操作的截屏: 上一页 [1] [2] [3] [4] [5] 六、运行测试类输出结果: ----------test()---------- 更新Sequence最大值! 10061 10062 10063 10064 10065 10066 10067 10068 10069 10070 更新Sequence最大值! 10071 10072 10073 10074 10075 10076 10077 10078 10079 10080 Process finished with exit code 0 说明:这个Sequence工具很智能,当请求一个不存在的Sequence时,会自动生成一个Sequence,保存到数据库。当请求一个已经存在的Sequence时,会从Sequence载体的缓存中获取一个Sequence值返回,当Sequence载体的缓存值达到最大时,会自动重新初始化Sequence载体信息,并更新数据库记录信息。 上一页 [1] [2] [3] [4] [5]
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表