`
hai0378
  • 浏览: 532176 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java实现的Sequence工具

 
阅读更多
Java实现的Sequence工具
 
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载体信息,并更新数据库记录信息。
 
参考文档:《Java与模式》多例模式一章。以上代码仅仅是阎宏博士一个例子的具体实现。
分享到:
评论

相关推荐

    DNAsequence java_java_

    标题 "DNAsequence java_java_" 暗示我们讨论的是一个使用Java编程语言实现的与DNA序列分析相关的程序。描述中的 "algorithm that calculates the leap year" 提到的是计算闰年的算法,这可能是程序的一部分,用于...

    java通过Mysql实现类似oracle序列功能序列.rar

    在Java应用程序中,如果需要在MySQL环境中实现类似Oracle序列的功能,我们需要自己设计解决方案。以下是一些关键知识点的详细说明: 1. **Java连接MySQL**: - 首先,你需要使用JDBC(Java Database Connectivity...

    C#,JAVA UML建模工具 源代码

    本资源提供了C#和Java的UML建模工具源代码,这对于开发者来说是一个宝贵的参考资料,有助于理解和学习如何实现这样的工具,以及如何在实际项目中应用UML。 首先,我们来看看C#的相关知识点。C#是一种面向对象的编程...

    初探WSDL2JAVA工具的使用

    WSDL2JAVA工具是现代Web服务开发不可或缺的一部分,它通过自动化生成Java代码,极大地降低了开发Web服务的难度和复杂性,使得开发者能够更加专注于业务逻辑的实现。无论是对于初学者还是经验丰富的开发者来说,掌握...

    Java工具:高性能并发工具Disruptor简单使用

    Java工具:高性能并发工具Disruptor简单使用 在Java编程中,高效并发处理是优化系统性能的关键之一。Disruptor,由LMAX公司开源的一款并发框架,为处理高并发场景提供了一种新颖且高效的解决方案。它通过消除锁和...

    经典算法问题的java实现<一>

    在本资源中,我们关注的是"经典算法问题的java实现&lt;一&gt;",这通常涉及到计算机科学中的基础算法,特别是那些用Java编程语言实现的。这些算法是解决各种计算问题的关键,包括排序、搜索、图论、动态规划等。Java作为一...

    widget sequence

    6. **编程实践**:在实际的软件开发过程中,开发人员可能会使用特定的编程语言(如Java、C#或Python)来实现Widget Sequence,同时结合设计模式(如MVC,Model-View-Controller)来组织代码,确保组件之间的良好解耦...

    生成以日期开头,加4位数字,每次加1的工具类.如:201712140001

    首先,`CodeUtil.java`可能是实现这个功能的核心类。这个类可能包含一个方法,例如`generateSequenceId()`,用于生成上述格式的序列号。该方法内部可能会使用Java的`java.util.Calendar`或`java.time.LocalDate`来...

    m3u8转mp4工具包

    m3u8转mp4工具包 下载后执行命令: 1、java -jar m3u8tomp4-1.0.jar https://*****/index.m3u8 /Users/***/Downloads/ /Users/***/Downloads/ 2、main方法接收三个参数 args[0] 下载地址 args[1] 文件保存地址 args...

    java实现简单的验证码功能

    下面将详细介绍如何使用Java实现这个功能。 首先,我们需要创建一个类,如`generateCode`,来生成验证码和对应的图像。在这个类中,定义了几个关键的静态变量,包括图像的宽度和高度(`width`和`height`),验证码...

    java解析ASN.1文件的实例和简要使用说明

    在这个示例中,我们有一个eclipse工程,这意味着你可以直接在Eclipse集成开发环境中运行和调试代码,这对于学习和理解ASN.1的Java实现非常有帮助。 在使用JAC时,首先你需要有一个asn.1文件,这个文件包含了你要...

    学生注册系统 uml java实现

    接下来,进入Java实现阶段。Java作为一种面向对象的编程语言,其强大的类库和跨平台特性使其成为实现学生注册系统的一个理想选择。 1. **类结构**:根据UML类图,我们将在Java中创建相应的类,如`Student`、`Course...

    java 解析ASN.1 编码格式cdr话单文件例子

    1. **引入Bouncy Castle库**:在项目中添加Bouncy Castle的依赖,通常通过Maven或Gradle来实现。对于Maven,可以在pom.xml中添加如下依赖: ```xml &lt;groupId&gt;org.bouncycastle &lt;artifactId&gt;bcpkix-jdk15on ...

    jude java 建模工具

    **Java建模工具JUDE详解** 在软件开发过程中,模型是理解和表述系统设计的关键。统一建模语言(UML)作为一种标准化的建模方法,广泛应用于软件工程领域。JUDE(Java Use Case Diagram Editor)就是一款专为Java...

    JAVA生成订单号(日期+流水号)

    在Java编程中,生成订单号...对于提供的`java订单号(时间加流水号).txt`文件,可能包含了具体的代码实现或使用示例,你可以查阅该文件以获取更详细的实现细节。在实际开发中,务必根据业务需求进行适当的调整和优化。

    用Jpcap和Java实现图形化的Ping程序.pdf

    ### 用Jpcap和Java实现图形化的Ping程序 #### 1. 引言 Ping程序作为一种常用的网络诊断工具,广泛应用于检测网络连通性和主机可达性。传统的Ping程序主要在命令行界面运行,这对于习惯了图形用户界面的用户来说...

    关于bioJava(1)

    在开发过程中,利用`bioJava`作为工具可以大大提升效率,例如,通过`bioJava`的API,可以快速实现一个序列比对的命令行工具,或者创建一个用于分析基因组数据的Web服务。 **总结** `bioJava`是生物信息学领域的一...

    JAXB 利用xsd文件生成java类

    JAXB (Java Architecture for XML Binding) 是Java平台上的一个标准,用于将XML文档与Java对象之间进行绑定,实现XML数据的解析和序列化。在Java开发中,JAXB提供了一种方便的方式,允许开发者通过XML Schema (XSD) ...

    Java Call Trace to UML Sequence Diagram-开源

    Java Call Trace to UML Sequence Diagram作为开源项目,意味着开发者可以查看其内部实现,学习其工作原理,甚至根据自己的需求进行定制。这种开放性促进了社区的合作与创新,使得工具能够持续改进和扩展。 在使用...

    使用Java创建音乐制作工具 - 一个实战教程

    10. 总结通过本实战教程,您已经了解了如何使用Java创建一个简单的音乐制作工具。从项目概述到实际的编程实现,包括GUI设计、音乐表示、音乐播放和音频导出,这些都是开发此类应用程序的关键步骤。随着技能的提高,...

Global site tag (gtag.js) - Google Analytics