Java实现的Sequence工具

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:
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; 
    } 
}
 
二、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(); 
    } 
}
 
三、简单的数据库连接工具
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(); 
            } 
        } 
    } 
}
 
四、测试类(客户端)
package sequence; 

/** 
* Created by IntelliJ IDEA. 
* User: leizhimin 
* Date: 2008-4-2 15:31:30 
* Company: LavaSoft([url]http://lavasoft.blog.51cto.com[/url]) 
* 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 
-- [url]http://lavasoft.blog.51cto.com[/url] 
-- 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载体信息,并更新数据库记录信息。

本文转自 leizhimin 51CTO博客,原文链接:http://blog.51cto.com/lavasoft/69682,如需转载请自行联系原作者
相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
数据采集 编解码 Java
解锁Hutool魔法箱:Java开发者不可错过的神奇工具集
解锁Hutool魔法箱:Java开发者不可错过的神奇工具集
58 0
|
2月前
|
缓存 监控 Java
线程池的魔法:Java 开发者必备的并发工具
线程池的魔法:Java 开发者必备的并发工具
44 0
|
3月前
|
存储 Java 数据安全/隐私保护
探索Java中神奇的ThreadLocal:为什么它是多线程编程的重要工具?
探索Java中神奇的ThreadLocal:为什么它是多线程编程的重要工具?
|
26天前
|
Java
java中日期处理的一些工具方法
java中日期处理的一些工具方法
16 1
|
25天前
|
安全 Java 数据安全/隐私保护
提升 Java 编程安全性 - 代码加密混淆工具的重要性和应用
提升 Java 编程安全性 - 代码加密混淆工具的重要性和应用
|
25天前
|
安全 Java 数据安全/隐私保护
探讨 Java 代码混淆加固工具
探讨 Java 代码混淆加固工具
|
27天前
|
存储 安全 Java
基于Java的qq截图工具(毕业设计含源码)
基于Java的qq截图工具(毕业设计含源码)
28 0
|
1月前
|
监控 NoSQL Java
性能工具之 Java 调试工具 JDB
【2月更文挑战第25天】性能工具之 Java 调试工具 JDB
32 4
|
1月前
|
Cloud Native Java 开发者
Spring Boot 4.0:构建云原生Java应用的前沿工具
Spring Boot 4.0:构建云原生Java应用的前沿工具