Java实现的Sequence工具

来源:互联网 发布:传奇霸业数据汇总 编辑:程序博客网 时间:2024/05/01 06:19
导读:
  Java实现的Sequence工具
  
  Sequence是数据库应用中很重要的一个特性,可是有些数据库没有这个特性,比如很流行的开源数据库MySQL就没有Sequence,利用自增主键感觉很不爽,每个表的ID都要设置,通用性也不好。因此考虑为这些不支持Sequence的数据做一个Sequence工具。自动为整个系统提供主键生成策略。
  
  下面是一个Sequence实现,以数据库MySQL为平台。源代码如下:
  
  一、Sequence工具类
  packagesequence;
  importjava.util.HashMap;
  importjava.util.Map;
  importjava.sql.SQLException;
  /**
  * Created by IntelliJ IDEA.

  * User: leizhimin

  * Date: 2008-4-2 15:21:30

  * Note: Java实现的Sequence工具
  */
  publicclassSequenceUtils {
  privatestaticSequenceUtils _instance = newSequenceUtils();
  privateMap keyMap = newHashMap(20); //Sequence载体容器
  privatestaticfinalintPOOL_SIZE = 10; //Sequence值缓存大小
  /**
  * 禁止外部实例化
  */
  privateSequenceUtils() {
  }
  /**
  * 获取SequenceUtils的单例对象
  * @return SequenceUtils的单例对象
  */
  publicstaticSequenceUtils getInstance() {
  return_instance;
  }
  /**
  * 获取下一个Sequence键值
  * @param keyName Sequence名称
  * @return 下一个Sequence键值
  */
  publicsynchronizedlonggetNextKeyValue(String keyName) {
  KeyInfo keyInfo = null
  Long keyObject = null
  try{
  if(keyMap.containsKey(keyName)) {
  keyInfo = keyMap.get(keyName);
  } else{
  keyInfo = newKeyInfo(keyName, POOL_SIZE);
  keyMap.put(keyName, keyInfo);
  }
  keyObject = keyInfo.getNextKey();
  } catch(SQLException e) {
  e.printStackTrace();
  }
  returnkeyObject;
  }
  }
  
  二、Sequence载体
  packagesequence;
  importjava.sql.*;
  /**
  * Created by IntelliJ IDEA.

  * User: leizhimin

  * Date: 2008-4-2 15:24:52

  * Note: Sequence载体
  */
  publicclassKeyInfo {
  privatelongmaxKey; //当前Sequence载体的最大值
  privatelongminKey; //当前Sequence载体的最小值
  privatelongnextKey; //下一个Sequence值
  privateintpoolSize; //Sequence值缓存大小
  privateString keyName; //Sequence的名称
  privatestaticfinalString sql_update = "UPDATE KEYTABLE SET KEYVALUE = KEYVALUE + ? WHERE KEYNAME = ?"
  privatestaticfinalString sql_query = "SELECT KEYVALUE FROM KEYTABLE WHERE KEYNAME = ?"
  publicKeyInfo(String keyName, intpoolSize) throwsSQLException {
  this.poolSize = poolSize;
  this.keyName = keyName;
  retrieveFromDB();
  }
  publicString getKeyName() {
  returnkeyName;
  }
  publiclonggetMaxKey() {
  returnmaxKey;
  }
  publiclonggetMinKey() {
  returnminKey;
  }
  publicintgetPoolSize() {
  returnpoolSize;
  }
  /**
  * 获取下一个Sequence值
  *
  * @return 下一个Sequence值
  * @throws SQLException
  */
  publicsynchronizedlonggetNextKey() throwsSQLException {
  if(nextKey >maxKey) {
  retrieveFromDB();
  }
  returnnextKey++;
  }
  /**
  * 执行Sequence表信息初始化和更新工作
  *
  * @throws SQLException
  */
  privatevoidretrieveFromDB() throwsSQLException {
  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();
  }
  }
  
  三、简单的数据库连接工具
  packagesequence;
  importjava.sql.*;
  /**
  * 简单的数据连接工具
  * File: DBUtils.java
  * User: leizhimin
  * Date: 2008-3-18 15:19:12
  */
  publicclassDBUtils {
  publicstaticfinalString url = "jdbc:mysql://127.0.0.1:3306/testdb";
  publicstaticfinalString username = "root"
  publicstaticfinalString password = "leizhimin"
  publicstaticfinalString driverClassName = "com.mysql.jdbc.Driver"
  /**
  * 获取数据库连接Connection
  *
  * @return 数据库连接Connection
  */
  publicstaticConnection 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();
  }
  returnconn;
  }
  publicstaticvoidmain(String args[]) {
  testConnection();
  }
  /**
  * 测试连接方法
  */
  publicstaticvoidtestConnection() {
  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();
  }
  }
  }
  }
  
  四、测试类(客户端)
  packagesequence;
  /**
  * Created by IntelliJ IDEA.
  * User: leizhimin
  * Date: 2008-4-2 15:31:30
  * Company: LavaSoft(http://lavasoft.blog.51cto.com)
  * Sequence测试(客户端)
  */
  publicclassTestSequence {
  /**
  * 测试入口
  * @param args
  */
  publicstaticvoidmain(String args[]) {
  test();
  }
  /**
  * 测试Sequence方法
  */
  publicstaticvoidtest() {
  System.out.println("----------test()----------");
  for(inti = 0; i <20; i++) {
  longx = 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;
  
  数据库操作的截屏:
  
  
  
  六、运行测试类输出结果:
  ----------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载体信息,并更新数据库记录信息。
  
  参考文档:《Java与模式》多例模式一章。以上代码仅仅是阎宏博士一个例子的具体实现。
  
  
  本文出自 “熔 岩” 博客,转载请与作者联系!

本文转自
http://lavasoft.blog.51cto.com/62575/69682
原创粉丝点击