作者:
Flyingis
在前面的一篇日志里面,我设计了在数据库表中自动生成ID号的一种算法(
点击这里查看),这个算法主要应用于字典表的修改中。字典表的ID号是这样设计的:A01、A05、A28等等,即一位字母+两位数字。由于每个字典表的ID号的第一个字母对于一个字典表来说是固定的,这样做的目的在于在其它表中查看数据的时候可以很容易分辨字典项的ID号是属于哪一个数据字典的,因此这就限制了每个字典表的数据不能超过99条,当数据量大于99条的时候,那个算法就不再适用。
因此这里给出了一个改进的算法(其实只作了一点点改进),可以满足数据在1~999条之间的数据字典,这对于绝大多数应用来说已经是绰绰有余了。下面就给出具体的方法:
/*
* 功能:增加字典信息时,自动生成最小的ID号码
* 参数:String 字典表名称 first 字典ID的首字母,代表唯一的字典
* 返回:String 生成的最小ID号码
*/
public String getId(String table, String first) {
// 所有除去首字母后的ID号码--整型,例如:11
int[] sid;
// 所有原始ID号码,例如:A011
String[] rid;
// 除去首字母后最小的ID号码--字符串
String sid_new = null;
// 程序返回的最小的原始ID号码
String rid_new = null;
// 循环参数
int i = 0;
int k = 0;
con = DatabaseConnection.getConnection("jdbc/wutie";
Statement stm = null;
ResultSet rst = null;
RowSet rowRst = null;
String sql = "SELECT * FROM " + table + " order by id";
try {
if (con.isClosed()) {
throw new IllegalStateException("error.sql.unexpected";
}
stm = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
rst = stm.executeQuery(sql);
while (rst.next()) {
k++;
}
sid = new int[k];
rid = new String[k];
rst = stm.executeQuery(sql);
// 如果不存在结果集,则直接在first字母后面加001,例如first="A",rid_new=A001
if (!rst.first()) {
rid_new = first.concat("001";
return rid_new;
}
// 如果存在结果集,则将表中所有ID号存入数组中,并转换为整型数据
else {
/*
while (rst.next()) {
rid[i] = rst.getString("id";
sid[i] = Integer.parseInt(rid[i].substring(1));
i++;
}
*/
for (rst.previous(); rst.next(); i++) {
rid[i] = rst.getString("id";
sid[i] = Integer.parseInt(rid[i].substring(1));
}
// 如果第一条记录ID号不为fisrt+001,例如A003、A018、A109等,则返回新增数据的ID号为A001
if (sid[0] != 1) {
rid_new = first.concat("001";
return rid_new;
}
// 如果第一条记录ID号为first+001,即A001,则执行下面语句
else {
// 如果总记录数只有一条,例如A001,则返回新增数据为A002
if (i == 1) {
rid_new = first.concat("002";
return rid_new;
}
else {
for (int j = 1; j < k; j++) {
// 如果相邻两条记录ID号的整数位相差1,则保存新增数据ID号整数位是前一位ID号整数位加1
if (sid[j] == sid[j-1] + 1) {
if (sid[j] < 9) {
sid_new = String.valueOf(sid[j] + 1);
rid_new = first.concat("00".concat(sid_new);
}
else if (sid[j]>9 && sid[j]<100){
sid_new = String.valueOf(sid[j] + 1);
rid_new = first.concat("0").concat(sid_new);
}
else {
sid_new = String.valueOf(sid[j] + 1);
rid_new = first.concat(sid_new);
}
}
// 如果相邻两条记录ID号的整数位相差非1,则返回新增数据ID号整数位是前一位ID号整数位加1
if (sid[j] != sid[j-1] + 1) {
if (sid[j-1] < 9) {
sid_new = String.valueOf(sid[j-1] + 1);
rid_new = first.concat("00".concat(sid_new);
return rid_new;
}
else if (sid[j]>9 && sid[j]<100){
sid_new = String.valueOf(sid[j-1] + 1);
rid_new = first.concat("0").concat(sid_new);
}
else {
sid_new = String.valueOf(sid[j-1] + 1);
rid_new = first.concat(sid_new);
return rid_new;
}
}
}
return rid_new;
}
}
}
}
catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("error.sql.runtime";
}
finally {
try {
stm.close();
con.close();
}
catch (SQLException e1) {
e1.printStackTrace();
throw new RuntimeException("error.sql.runtime";
}
}
}
注意:之所以生成A01而不是A1,是因为在SQLServer2000中根据ID号正确排序的需要,如果按照升序排列,A1后面是A10、A11等,而不是A2。另外,在Hibernate中有多种自动生成ID字段的方法,但是这个项目比较小,我没有使用Hibernate中间件,这里提供的只是生成字典ID字段的一种简单思路,相比
原有算法改进了一点,可以适用于字典项不多于1000项的情况,一般情况下,字典项是不可能超过1000项了,在我参与的这个小项目中已经是完全够用了。还有什么更好的方法和思路还请大家多指教!