您的位置:首页 > 产品设计 > UI/UE

Java实现的Sequence工具 - 2

2014-12-13 08:20 399 查看
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;
}

}


?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: