Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 316|回复: 0

[Java基础知识]一个用java实现的数据库序列生成器

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-1 03:50:56 | 显示全部楼层 |阅读模式
    一个用java实现的数据库序列生成器  

        如果是集群等应用这个就不行了,只能在单应用的情况下使用。 对于每个序列键只需在第一次使用时查询数据库,后面的都将不需要查询。 有非常详细的注释,我就不多说了。


    package org.shaoye.common.sql;

    import java.util.HashMap;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
      
      
       
       
       

       
      
    ?
      
    /**
    * 类<code>Key</code>是一个数据库主键生成器,用序列号的方式来产生数据库中需要的主键值。
    * <p>
    * <code>Key</code>目前支持的数据库包括Oracle的所有版本、MySql的3.x以上的版本
    * 以及所有支持max()函数的数据库,支持字段类型仅为数字类型的主键,对于字符及其它类型的主键尚不提供支持。
    * <p>
    * 在使用时只需提供表名、字段名(主键)以及到数据库的JDBC连接,如果想要获得message表的id字段的下一个
    * 主键值时:
    * <p><blockquote><pre>
    * java.sql.Connection conn = ...;
    * org.shaoye.common.sql.Key key = org.shaoye.common.sql.Key.getInstance();
    * int keyValue = key.getNextKey("message", "id", conn);
    * String sql = "insert into message (id,...) values (" + keyValue + ",...)";
    * //执行插入操作...
    * </pre></blockquote><p>
    *
    * @author 令少爷(shaoye@vip.sina.com)
    * @since magic 0.1
    */
    public final class Key {

      /**
      * key的最大值,默认为9223372036854775807,即long类型的最大值
      */
      private long max = 9223372036854775807L;

      /**
      * key的最小值,默认为1
      * */
      private long min = 1L;

      /**
      * Key的唯一实例,通过getInstance()方法获得
      * */
      private static Key keygen = new Key();

      /**
      * KeyInfo类的实例列表,默认容量为5个
      * */
      private HashMap keyList = new HashMap(5); //keyInfo 列表

      /**
      * 私有的默认构造方法,防止外部构造类的实例
      * */
      private Key() {
      }

      /**
      * 获得Key的唯一实例
      * */
      public static Key getInstance() {
           return keygen;
      }

    /**
    * 用指定的表和字段获得key的下一个值,主键的值不得超过2147483647
    * @param tableName 数据库中的表名,表中必须有一个数字主键
    * @param keyName 表(tableName)中的字段名
    * @param conn JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
    * @return key的下一个主键的int值
    * @throws <code>KeyException</code> 如果表名或字段名不存在、访问数据库错误或key的值大于2147483647时抛出
    */
    public int getNextKey(String tableName, String keyName, Connection conn) throws KeyException {
         long value = getNextKeyLong(tableName, keyName, conn);
         if (value > 2147483647L) {
            throw new KeyException("Key"s value too big,please call getNextKeyLong method!");
         }
         return (new Long(value)).intValue();
      }

    /**
    * 用指定的表和字段获得key的下一个值,最大为9223372036854775807
    * @param tableName 数据库中的表名,表中必须有一个数字主键
    * @param keyName 表(tableName)中的字段名
    * @param conn JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
    * @return key的下一个主键的long值
    * @throws <code>KeyException</code> 如果表名或字段名不存在或访问数据库错误时抛出
    */
    public long getNextKeyLong(String tableName, String keyName, Connection conn)throws KeyException {
        KeyInfo keyinfo;
        String item = tableName + "." + keyName;
        try {
                if (keyList.containsKey(item)) {
                     keyinfo = (KeyInfo) keyList.get(item);
                }else {
                     keyinfo = new KeyInfo(tableName, keyName, conn);
                     keyList.put(item, keyinfo);
                }
                return keyinfo.getNextKey();
         }catch (SQLException sqle) {
                   throw new KeyException(sqle);
         }
    }

    /**
    * 用指定的"表<code>.</code>字段"形式的字符串获得key的下一个值,主键的值不得超过2147483647
    * @param tableDotField "表.字段"形式的字符串,如:message.id
    * @param conn JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
    * @return key的下一个主键的int值
    * @throws <code>KeyException</code> 如果表名或字段名不存在、访问数据库错误或key的值
    * 大于2147483647时抛出
    */
    public int getNextKey(String tableDotField, Connection conn) throws KeyException {
        long value = getNextKeyLong(tableDotField, conn);
        if (value > 2147483647L) {
           throw new KeyException("Key"s value too big,please call getNextKeyLong method!");
        }
        return (new Long(value)).intValue();
    }

    /**
    * 用指定的"表<code>.</code>字段"形式的字符串获得key的下一个值,最大为9223372036854775807
    * @param tableDotField "表.字段"形式的字符串,如:message.id
    * @param conn JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
    * @return key的下一个主键的int值
    * @throws <code>KeyException</code> 如果表名或字段名不存在或访问数据库错误时抛出
    */
    public long getNextKeyLong(String tableDotField, Connection conn) throws KeyException {
        int dot_index = tableDotField.indexOf(".");
        if (tableDotField.indexOf(".") < 1) {
            throw new KeyException("Unknown Key "" + tableDotField + ""!");
        }
        String tab = tableDotField.substring(0, dot_index);
        String key = tableDotField.substring(dot_index);
        return getNextKeyLong(tab, key, conn);
    }

    /**
    * 用指定的表和字段获得key的当前值,主键的值不得超过2147483647
    * @param tableName 数据库中的表名,表中必须有一个数字主键
    * @param keyName 表(tableName)中的字段名
    * @param conn JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
    * @return key的当前int值
    * @throws <code>KeyException</code> 如果表名或字段名不存在、访问数据库错误或key的值大于2147483647时抛出
    */
    public int getCurrentKey(String tableName, String keyName, Connection conn)throws KeyException {
        long value = getCurrentKeyLong(tableName, keyName, conn);
        if (value > 2147483647L) {
         throw new KeyException("Key"s value too big,please call getCurrentKeyLong method!");
        }
        return (new Long(value)).intValue();
    }

    /**
    * 用指定的表和字段获得key的当前值,最大为9223372036854775807
    * @param tableName 数据库中的表名,表中必须有一个数字主键
    * @param keyName 表(tableName)中的字段名
    * @param conn JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
    * @return key的当前long值
    * @throws <code>KeyException</code> 如果表名或字段名不存在或访问数据库错误时抛出
    */
    public long getCurrentKeyLong(String tableName, String keyName, Connection conn)throws KeyException {
         KeyInfo keyinfo;
         String item = tableName + "." + keyName;
         try {
              synchronized (keyList) {
               if (keyList.containsKey(item)) {
                    keyinfo = (KeyInfo) keyList.get(item);
               }else {
                    keyinfo = new KeyInfo(tableName, keyName, conn);
                    keyList.put(item, keyinfo);
               }
              }
              return keyinfo.getCurrentKey();
          }catch (SQLException sqle) {
                    throw new KeyException(sqle);
          }
    }

    /**
    * 用指定的"表<code>.</code>字段"形式的字符串获得key的当前值,主键的值不得超过2147483647
    * @param tableDotField "表.字段"形式的字符串,如:message.id
    * @param conn JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
    * @return key的当前int值
    * @throws <code>KeyException</code> 如果表名或字段名不存在、访问数据库错误或key的值
    * 大于2147483647时抛出
    */
    public int getCurrentKey(String tableDotField, Connection conn) throws KeyException {
        long value = getCurrentKeyLong(tableDotField, conn);
        if (value > 2147483647L) {
          throw new KeyException("Key"s value too big,please call getNextKeyLong method!");
        }
        return (new Long(value)).intValue();
    }

    /**
    * 用指定的"表<code>.</code>字段"形式的字符串获得key的当前值,最大为9223372036854775807
    * @param tableDotField "表.字段"形式的字符串,如:message.id
    * @param conn JDBC连接,如果欲获得的key是第一次取值,则必须保证conn能连接到数据库
    * @return key的当前int值
    * @throws <code>KeyException</code> 如果表名或字段名不存在或访问数据库错误时抛出
    */
    public long getCurrentKeyLong(String tableDotField, Connection conn) throws KeyException {
         int dot_index = tableDotField.indexOf(".");
         if (tableDotField.indexOf(".") < 1) {
           throw new KeyException("Unknown Key "" + tableDotField + ""!");
         }
         String tab = tableDotField.substring(0, dot_index);
         String key = tableDotField.substring(dot_index);
         return getCurrentKeyLong(tab, key, conn);
      }
    }


      /**
      * 内部类,用来存储主键信息
      * */
    class KeyInfo {
      private long max = 9223372036854775807L;
      private long min = 1L;
      private long nextKey;
      private String tableName;
      private String keyName;
      private Connection conn = null;

      /**
      * keyInfo 对象初始化
      */
      KeyInfo(String tableName, String keyName, Connection _conn) throws SQLException {
        this.tableName = tableName;
        this.keyName = keyName;
        this.conn = _conn;
        retrieveFromDB();
      }

      int getMax() {
            return (new Long(max)).intValue();
       }
       
       long getMaxLong() {
            return max;
      }

       int getMin() {
                return (new Long(min)).intValue();
       }

       long getMinLong() {
                return min;
      }

      /**
      * 取下一键值
      */
      int getNextKey() {
           return (new Long(getNextKeyLong())).intValue();
      }

      /**
      * 取下一键值
      */
      synchronized long getNextKeyLong() {
               nextKey++;
               return nextKey;
      }

      /**
      * 取当前键值
      */
      synchronized int getCurrentKey() {
              return (new Long(nextKey)).intValue();
      }

      /**
      * 取当前键值
      */
      synchronized long getCurrentKeyLong() {
           return nextKey;
      }

      /**
      * 从数据库中取当前最大值
      */
      void retrieveFromDB() throws SQLException {
           PreparedStatement pstmt = null;
           ResultSet rs = null;
           int keyFromDB = 0;
           String sql = "select max(" + keyName + ") from " + tableName;
           try {
                  pstmt = conn.prepareStatement(sql);
           }catch (Exception ex) {
                  throw new KeyException("Can"t connect DataBase!");
           }
           try {
                  rs = pstmt.executeQuery();
           }catch (SQLException sqle) {
                if (pstmt != null)
                pstmt.close();
                throw new KeyException(""" + keyName + "" or "" + tableName + "" isn"t exist in DataBase!",sqle);
          }
          try {
                if (rs.next()) {
                    nextKey = rs.getLong(1);
                    if (nextKey < min) {
                            nextKey = min;
                    }
                }else {
                            nextKey = min;
                }
          }catch (SQLException sqle) {
                            throw (sqle);
          }
          finally {
                    if (rs != null)
                              rs.close();
                    if (pstmt != null)
                              pstmt.close();
          }
        }
    }
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-28 23:59 , Processed in 0.467009 second(s), 48 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

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