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(http://lavasoft.blog.bitscn.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.bitscn.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实现的Sequence工具 的全部内容, 来源链接: utcz.com/p/206199.html

回到顶部