博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一个生成全局唯一Sequence ID的高并发工厂类 (Java)
阅读量:6570 次
发布时间:2019-06-24

本文共 5529 字,大约阅读时间需要 18 分钟。

  hot3.png

Sequence是数据库系统按照一定规则自动增加的数字序列。这个序列一般作为代理主键(因为不会重复),没有其他任何意义。 

Sequence是数据库系统的特性,有的数据库实现了Sequence,有的则没有。比如Oracle、DB2、PostgreSQL数据库实现Sequence, 而MySQL、SQL Server、Sybase等数据库没有Sequence。

那么如何给一个不支持Sequence的数据库增加支持呢?

下面将给出Java版本的代码。这个代码还实现了对 Sequence ID的高效缓存,并不是每一次调用都会对数据库进行访问,在高并发环境下性能优异。

1. SequenceId.java

package uuid;public class SequenceId {    public static final long NOT_FOUND = 0;    private static final long STEP = 100;    private final SequenceIdProvider provider;    private final String name;    private final long beginValue;    private long value;    protected SequenceId(SequenceIdProvider provider, String name, long beginValue) {        this.provider = provider;        this.name = name;        this.beginValue = beginValue;        this.value = -1;        if (beginValue <= 0) {            throw new IllegalArgumentException("begin value must be great than zero.");        }    }    public String getName() {        return name;    }    public synchronized long nextVal() {        if (value < 0) {            value = provider.load(name);            if (value <= NOT_FOUND) {                value = beginValue - 1;            }            provider.store(name, value + STEP);        }        value++;        if (value % STEP == 0) {            provider.store(name, value + STEP);        }        return value;    }}
2. SequenceIdProvider.java

package uuid;public interface SequenceIdProvider {        public SequenceId create(String name);        public SequenceId create(String name, long begin);        public long load(String name);    public void store(String name, long value);    }
3. JdbcSequenceIdProvider.java

package uuid;import java.sql.*;import javax.sql.DataSource;public class JdbcSequenceIdProvider implements SequenceIdProvider {    private static final String TABLE_NAME = "_SEQUENCE_";    private final DataSource dataSource;    public JdbcSequenceIdProvider(DataSource dataSource) {        this.dataSource = dataSource;        confirmTableExists();    }    @Override    public SequenceId create(String name) {        return new SequenceId(this, name, 1);    }    @Override    public SequenceId create(String name, long begin) {        return new SequenceId(this, name, begin);    }    private void confirmTableExists() {        Connection conn = null;        try {            conn = dataSource.getConnection();            ResultSet rs = conn.getMetaData().getTables(null, null, TABLE_NAME, null);            boolean found = rs.next();            rs.close();            if (!found) {                Statement stmt = conn.createStatement();                String sql = "create table " + TABLE_NAME + " (name varchar(50) not null, next_val long not null, primary key(name))";                stmt.execute(sql);                stmt.close();            }        } catch (SQLException e) {            throw new RuntimeException(e);        } finally {            close(conn);        }    }    private void close(Connection conn) {        if (conn != null) {            try {                conn.close();            } catch (SQLException e) {                throw new RuntimeException(e);            }        }    }    @Override    public long load(String name) {        long value = SequenceId.NOT_FOUND;        Connection conn = null;        try {            conn = dataSource.getConnection();            String sql = "select next_val from " + TABLE_NAME + " where name=?";            PreparedStatement ps = conn.prepareStatement(sql);            ps.setString(1, name);            ResultSet rs = ps.executeQuery();            if (rs.next()) {                value = rs.getLong(1);            }            rs.close();            ps.close();        } catch (SQLException e) {            throw new RuntimeException(e);        } finally {            close(conn);        }        return value;    }    @Override    public void store(String name, long value) {        Connection conn = null;        try {            conn = dataSource.getConnection();            String sql = "update " + TABLE_NAME + " set next_val=? where name=?";            PreparedStatement ps = conn.prepareStatement(sql);            ps.setLong(1, value);            ps.setString(2, name);            int updated = ps.executeUpdate();            ps.close();            if (updated == 0) {                sql = "insert into " + TABLE_NAME + " (name, next_val) values (?,?)";                ps = conn.prepareStatement(sql);                ps.setString(1, name);                ps.setLong(2, value);                ps.executeUpdate();                ps.close();            }        } catch (SQLException e) {            throw new RuntimeException(e);        } finally {            close(conn);        }    }}
4. GlobalSequenceIdProvider.java

package uuid;import javax.sql.DataSource;public class GlobalSequenceIdProvider {    private static final SequenceId global;    private static final SequenceId table1;    private static final SequenceId table2;    static {        SequenceIdProvider provider = new JdbcSequenceIdProvider(getDataSource());        global = provider.create("global");        table1 = provider.create("table1");        table2 = provider.create("table2", 1000);    }    public static long nextVal() {        return global.nextVal();    }    public static long nextVal_table1() {        return table1.nextVal();    }    public static long nextVal_table2() {        return table2.nextVal();    }    private static DataSource getDataSource() {        // TODO:        return null;    }}

转载于:https://my.oschina.net/sub/blog/115758

你可能感兴趣的文章
wamp 与 phpstudy 中开启伪静态的区别
查看>>
使用AXIS生成SOAP Web Service客户端的方法
查看>>
[转]linux kill信号列表
查看>>
动态代理
查看>>
理解RESTful架构
查看>>
Mediawiki:禁止游客编辑注册
查看>>
探秘Java虚拟机——内存管理与垃圾回收-转
查看>>
Java开发重用库和API
查看>>
Android webview(三) addJavascriptInterface的安全问题
查看>>
react子组件调用父组件方法
查看>>
myeclipse10 快速搭建spring boot开发环境(入门)
查看>>
WorkFlow入门Step.4—Adding Procedural Elements-For...
查看>>
java-多线程
查看>>
Maven学习(五):版本管理
查看>>
Java 语句标签实现goto跳转
查看>>
层次聚类算法BIRCH(另附Java版下载地址)
查看>>
理解Linux系统负载
查看>>
样条表示---B样条曲面
查看>>
牛牛的闹钟
查看>>
探索 Android Design Support Library v28 新增内容
查看>>