现在我遇到了一个问题:为了生成一个序号,格式例如为:ES100001(ES:特征位,11:代表现在的年份2010年后两位,0001:表示数据库统计查询后的数字加1)。但是这样就遇到一个问题,比如A和B同一时间同步提交一个表单,就会生成同样的序号,如(ES100002),请问大伙儿有什么好的解决办法?我的伪代码是这样的:
 
   // 数据库查询
   int count = Query.doQuery(Long.class,"select count(*) from TableA where condition1=1");
   // 定义数据对象
   BeanA a = new BeanA(); 
   a.setName("Goods1");
   Generator ge = new Generator();
   // 传入统计查询后的统计数
   String order = ge.generateOrder(count); 
   a.setOrder(order);
   PersistanceUtil.save(order);如果AB两人同时提交的时候就会出现相同的序号问题,有什么机制能避免产生这种问题吗?我试过了Synchronized同步块,好像还有这个问题,各位大侠有什么好的解决方法吗?

解决方案 »

  1.   

    涉及到数据库,synchronized不一定有效,因为你可能有不只一个业务处理的类实例,这些不同的实例可以单独的访问数据库,这样synchronized也就控制不了了,所以,应该考虑锁表的方式,或者用数据库的sequence
      

  2.   

    自己手动处理的方法如下:
        单独建一张表专门用来存放ES100001这样的序号,表字段不要多,除了一个字段存放序号,还可以再加一个存放计数器的字段
        这张表一开始可以先准备好这样一条数据:序号为NULL(因为还没开始使用),计数器为0。
        当A需要用到序号向表中插入数据之前,先查这张特殊表,如果序号为空,默认序号为ES100001,如果序号不为空,按你说的,开始在JAVA里手动计算,排除ES,排除10,用0001做+1计算生成新的序号,查这张特殊表的时候要把计数器同时取出来,序号算好了,你现在不能保证这个序号就是唯一没有被B用过的,所以先不能用这个序号做插入动作,在这之前还要用这张特殊表做一件事:
    update table(假如这张特殊表表名叫table) set 序号=ES10001,计数器=计数器+1 where 计数器=参数
    意思就是:用你新生成的序号去更新这张表,同时把计数器+1,但条件是现在数据库里存放的数值要与你之前拿到的数值相等,否则就是在你计算的过程中已经有B这么一个人动过数据库,他已经先拿走了一个序号,你的不是最新的序号,那还要反复执行上面的过程,直到
    update table(假如这张特殊表表名叫table) set 序号=ES10001,计数器=计数器+1 where 计数器=参数
    这条更新语句能成功执行,那再用这个新的序号做你自己业务表的插入操作!