如何改造Java主键生成类以支持多次按范围生成递增主键?
问题分析与修改方案
原代码的核心问题是静态变量导致的实例间状态污染:upper_range和lower_range被定义为static,所有PrimaryGen实例共享这两个值,第二次创建实例时会覆盖第一次的范围配置,导致之前的实例生成主键逻辑完全混乱。结合你的使用场景(两次调用分别处理不同范围或续接范围的主键生成),需要做以下修改:
1. 将静态范围变量改为实例变量
把upper_range和lower_range的static修饰符去掉,让每个PrimaryGen实例拥有独立的范围配置,避免不同实例之间互相干扰:
public class PrimaryGen { private int upper_range; // 移除static修饰 private int lower_range; // 移除static修饰 private int counter; PrimaryGen(int upper,int lower) { // 新增:构造时校验范围合法性 if (lower > upper) { throw new IllegalArgumentException("下限不能大于上限"); } upper_range = upper; lower_range = lower; counter = lower_range - 1; } // 其他方法后续修改 }
2. 修正主键生成的边界判断逻辑
原getNextVal的判断条件错误,会导致生成超出upper_range的值。比如当counter等于upper_range时,原逻辑不会抛出异常,而是直接递增为upper_range+1并返回。需要调整判断时机,确保生成的主键始终在设定范围内:
int getNextVal() { // 先判断递增后是否超出范围 if (counter + 1 > upper_range) { throw new RuntimeException("主键超出设定范围"); } counter++; return counter; }
3. 支持续接范围的主键生成(可选)
如果你的场景是第二次调用需要基于第一次的最后生成值续接新范围(比如第一次生成1-10,第二次要生成11-20),可以新增一个重置范围的方法,无需创建新实例:
// 重置范围,用于续接生成主键 void resetRange(int newUpper, int newLower) { if (newLower > newUpper) { throw new IllegalArgumentException("下限不能大于上限"); } // 可选校验:确保新范围与上次生成的主键连续 if (newLower != counter + 1) { throw new IllegalArgumentException("新范围的下限必须与最后生成的主键连续"); } upper_range = newUpper; lower_range = newLower; }
4. 增加线程安全支持(可选)
如果这个类会在多线程环境下使用,需要给getNextVal和resetRange方法加上synchronized修饰,避免并发导致的主键重复或状态混乱:
synchronized int getNextVal() { // 原判断与递增逻辑 } synchronized void resetRange(int newUpper, int newLower) { // 原校验与重置逻辑 }
修改后的完整代码
public class PrimaryGen { private int upper_range; private int lower_range; private int counter; PrimaryGen(int upper, int lower) { if (lower > upper) { throw new IllegalArgumentException("下限不能大于上限"); } upper_range = upper; lower_range = lower; counter = lower_range - 1; } synchronized int getNextVal() { if (counter + 1 > upper_range) { throw new RuntimeException("主键超出设定范围"); } counter++; return counter; } // 可选:续接范围的重置方法 synchronized void resetRange(int newUpper, int newLower) { if (newLower > newUpper) { throw new IllegalArgumentException("下限不能大于上限"); } if (newLower != counter + 1) { throw new IllegalArgumentException("新范围的下限必须与最后生成的主键连续"); } upper_range = newUpper; lower_range = newLower; } }
使用示例
// 第一次调用:设置范围1-10,插入主键 PrimaryGen gen1 = new PrimaryGen(10, 1); for (int i = 0; i < 10; i++) { System.out.println(gen1.getNextVal()); // 输出1-10 } // 第二次调用:续接范围11-20,生成后续值 gen1.resetRange(20, 11); for (int i = 0; i < 10; i++) { System.out.println(gen1.getNextVal()); // 输出11-20 } // 或者创建新实例处理独立范围 PrimaryGen gen2 = new PrimaryGen(50, 30); System.out.println(gen2.getNextVal()); // 输出30
内容的提问来源于stack exchange,提问作者Just_CODING
相关产品推荐
相关产品推荐

