怎么生成流水号

怎么生成流水号,第1张

目前是在.net中使用的这个方法,使用sqlserver的时间戳来控制并发情况下容易产生重复序列号的问题。

原理类似hibernate的主键生成机制,在系统启动时从数据库中读出最大的流水号,赋给一个类的静态变量,需要时,从该静态变量中取得流水号,加1后,就是你要的值。

代码:

public class testA {

public static Long maxNo

static {

synchronized(maxNo){

maxNo = select max(maxNo) from DB

}

}

public synchronized static long getMaxNo(){

return(++maxNo)

}

}

优点:保证同步,不会取到相同的值,同时避免了数据库的反复读取。

缺点:在cluster环境下

还是用上面的方法,但是只能在一台机器上发布并且绑定到JNDI,别的机器可以通过配置文件得知去哪里产生maxNo(实际上,每台机器都可以发布,但是所有机器只能去访问指定的一台机器),这样的效率虽然低了点,但是还是觉得比每次去数据库里取好点。当然,可以改进,就是再加一个本地类,每次去JNDI那里的类去取数据时,一次取20个回来(就是JNDI上面的类一次要加20),以后本地就用这20个值,用完了,再去JNDI上面的类去取。

当然,前面的这两个例子都比较复杂,甚至还有人提出用单态的方法。而我在.net中用的就比较简单了。方法如下:

在数据库(sqlserver)中新建一张表(sequence_num),专门用来生成流水号。

字段1:s_id,varchar(50),notnull

字段2:tmstmp,timestamp,notnull

代码如下:

public string getOderid()

{

private SqlConnection conn = null

private SqlCommand comm = null

private string s_id = ""

private byte [] tmstmp//时间戳类型在.net中对应为一个byte数组

private int s_idplus = 0

private string orderid = ""

try

{

conn = SqlConn.getConn()

conn.Open()

do

{

string sqlQuery = "select s_id,tmstmp as tmstmp from sequence_num"

comm = conn.CreateCommand()

comm.CommandText = sqlQuery

SqlDataAdapter da = new SqlDataAdapter(comm)

DataTable dt = new DataTable()

dt.Clear()

da.Fill(dt)

comm.Parameters.Clear()

if (!dt.Rows[0]["s_id"].ToString().Substring(0,12).Equals(DateTime.Now.ToString("yyyyMMddHHmm")))//每一分钟重置一次计数,实际上我认为每天重置一次比较好

{

s_id = DateTime.Now.ToString("yyyyMMddHHmm")+"0001"

tmstmp = (byte[])dt.Rows[0]["tmstmp"]

}

else

{

s_id = dt.Rows[0]["s_id"].ToString()

tmstmp = (byte[])dt.Rows[0]["tmstmp"]

s_idplus = Convert.ToInt32(s_id.Substring(12)) + 1

s_id = s_id.Substring(0,12)+Convert.ToString(s_idplus).PadLeft(4,'0')

}

string sqlUpdate = "update sequence_num set s_id = @s_id where tmstmp = @tmstmp"//保证在记录未被修改的情况下更新,如果更新不成功,则重走一遍生成序列号的流程

comm.CommandText = sqlUpdate

comm.Parameters.Clear()

comm.Parameters.Add("@s_id",SqlDbType.VarChar,50)

comm.Parameters["@s_id"].Value = s_id

comm.Parameters.Add("@tmstmp",SqlDbType.Timestamp)

comm.Parameters["@tmstmp"].Value = tmstmp

}

while(comm.ExecuteNonQuery()<=0)

}

catch(SqlException ex)

{

string aaa = ex.Message

}

finally

{

if(conn!=null)

{

conn.Close()

}

}

return s_id

}

这个流程都是在.net里实现的,实际使用中可以通过存储过程来实现。当然,这种方法对数据库的访问会比较频繁,另外,数据库表建立的时候必须插入一条初始值,这是代码不完善的地方,有时间的话我会去完善它。只是判断如果表内没有记录的情况下就插入一条初始记录,这个时候如何处理并发问题还没想明白。

可以设计两个字段,

或者是,

你写一个方法然后取出来你要的最大值+

1然后得到的值,

再做计算,

思路:

1.sql

select

max(流水号)

from

表名

2.比方你上面的,

用字符串截取,

获得去掉前两位的数,

然后获得年月日,

然后呢,

在你的序号上增加一

3.然后等到了你要的数据HK201301050001,

或者,

你建两个字段,

一个显示流水号(也就是你要的值),

一个就不显示,

是这个表的序列号,

然后根据这个序列号去生成你要的HK年月日+

序列号(也就是第二个字段),

然后得到你要的值,

上面的可以用一个方法实现,

然后呢,

就去调用这个方法就行了

有什么要求吗?

一般有:

自增长列(对于oracle来说,用序列sequence来实现)

最大号 + 1

年月日 + 序号     -- 这儿的序号,就是上面的最大号+1,但是实现方法可能稍有区别


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/6770279.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-03-28
下一篇 2023-03-28

发表评论

登录后才能评论

评论列表(0条)

保存