Serial number generator

Source: Internet
Author: User

The database has self-growth fields, but the self-growth fields have their own limitations. Some databases do not support self-growth. In the development process, some customer businesses need to generate business process numbers, and simple numbers cannot meet their needs. Therefore, the idea of writing a serial number generator is generated.

1. First create a database table

Create Table sys_max_number (
Mn_id varchar (32) not null,
Mn_key_name varchar (64) not null,
Mn_key_value bigint not null default 0,
Mn_remark varchar (512) not null,
Constraint pk_sys_max_number primary key (mn_id ),
Constraint ak_unique_max_number_sys_max _ unique (mn_key_name)
)
Go

The meanings of each field are as follows: primary key of the database, key of the serial number, key value (0 by default), and description of the serial number key.

The Code is as follows:

Package com. SYS. maxnumber;

Import java. SQL. connection;
Import java. SQL. preparedstatement;
Import java. SQL. resultset;
Import java. SQL. sqlexception;

Import org. Apache. commons. Logging. log;
Import org. Apache. commons. Logging. logfactory;

Import com. Work. Core. DB. dbconnectionfactory;

/**
* @ Author wangmingjie
* @ Date 2009-8-4 09:59:15 AM
*/
Public class keyinfo {
Private Static log = logfactory. getlog (keyinfo. Class );
Private long keymax; // The maximum key value.
Private long keymin; // minimum key value
Private long nextkey; // The next key value
Private int poolsize; // cache size. Note that the number is too large to be wasted.
Private string keyname; // The application in which the primary key is used.

Public keyinfo (INT poolsize, string keyname ){
This. poolsize = poolsize;
This. keyname = keyname;
Retrievefromdb (5); // note that this class cannot be used directly; otherwise, a problem may occur in the case of multithreading.
// It must be called during initialization; otherwise, an error occurs! The purpose is to assign a value to nextkey first.
}

Public long getkeymax (){
Return keymax;
}

Public long getkeymin (){
Return keymin;
}

/**
* Obtain the key value of the Next string. If the length does not match, use zero to fill the front. <br>
* For example, if the parameter is four or intkey = 10, 0010 is returned.
* Note: The getnextintkey method is called here.
* 2,147,483,647,
* @ Param paddinglength
* String length. The maximum length is 10 characters. Because of the integer.
*
* @ Return if the parameter length is greater than the specified length, the actual length of the string is returned.
*/
Public String getnextstringkey (final int paddinglength ){
String S = long. tostring (getnextintkey ());
Int Len = S. Length ();
If (LEN <paddinglength ){
Stringbuffer Buf = new stringbuffer (paddinglength );
For (INT I = 0; I <paddinglength-len; I ++ ){
Buf. append ('0 ');
}
Buf. append (s );
S = Buf. tostring ();
}
Return S;
}

/**
* Obtain the key value of the next integer;
*
* @ Return
*/
Public synchronized int getnextintkey (){
If (nextkey> keymax ){
Retrievefromdb (5 );
}
Return (INT) (nextkey ++ );
}
 
/**
* Obtain the key value of the long integer.
* @ Return
*/
Public synchronized long getnextlongkey (){
If (nextkey> keymax ){
Retrievefromdb (5 );
}
Return nextkey ++;
}

Private void retrievefromdb (INT count ){
If (COUNT = 0 ){
If (log. iserrorenabled ())
Log. Error ("An error occurred while obtaining the serial number! Abandon acquiring ...");
Return;
}
Boolean success = false;

Long keyfromdb = 0;
String updatesql = "Update sys_max_number set mn_key_value = mn_key_value +"
+ Poolsize + "where mn_key_name =? ";

String selectsql = "select mn_key_value from sys_max_number where mn_key_name =? ";
Connection conn = NULL;
Preparedstatement pstupdate = NULL;
Preparedstatement pstselect = NULL;
Resultset rst = NULL;
Try {
// Conn = dbconnectionfactory. getjdbcconn ();
Conn = dbconnectionfactory. getconnection (); // obtain the database connection from the connection pool
Conn. setautocommit (false );
Pstupdate = conn. preparestatement (updatesql );
Pstupdate. setstring (1, keyname. Trim ());
Pstupdate.exe cuteupdate ();

Pstselect = conn. preparestatement (selectsql );
Pstselect. setstring (1, keyname. Trim ());
RST = pstselect.exe cutequery ();
While (RST. Next ()){
Keyfromdb = RST. getlong (1 );
}
Conn. Commit ();
Success = true;
} Catch (sqlexception e ){
Try {
Conn. rollback ();
} Catch (sqlexception E1 ){
E1.printstacktrace ();
}
E. printstacktrace ();
If (log. iswarnenabled ())
Log. Warn ("failed to get the serial number! ", E );
} Finally {

Try {
If (RST! = NULL)
RST. Close ();
} Catch (sqlexception e ){
}
Try {
If (pstupdate! = NULL)
Pstupdate. Close ();
} Catch (sqlexception e ){
}
Try {
If (pstselect! = NULL)
Pstselect. Close ();
} Catch (sqlexception e ){
}
Try {
If (Conn! = NULL)
Conn. Close ();
} Catch (sqlexception e ){
}
}

Keymax = keyfromdb;
Keymin = keyfromdb-poolsize + 1;
Nextkey = keymin;

If (! Success ){
If (log. iswarnenabled ())
Log. Warn ("Warning, failed to get the next serial number due to thread contention. Perform the next attempt ...");
// Call this method again, but sleep briefly to try to avoid thread contention.
Try {
Thread. Sleep (75 );
} Catch (interruptedexception IE ){
}
Retrievefromdb (count-1 );
}
}
}

==============================================

Package com. SYS. maxnumber;

Import java. util. hashmap;
//
// Import org. Apache. commons. Logging. log;
// Import org. Apache. commons. Logging. logfactory;

/**
* @ Author wangmingjie
* @ Date 2009-8-4 10:33:19 AM
*/
Public class keygenerator {
// Private Static log = logfactory. getlog (keygenerator. Class );
 
Private Static hashmap <string, keygenerator> kengens = new hashmap <string, keygenerator> (
10 );
/* The minimum value is 1, because the default value in the database is 0, and the generated sequence value is at least 1 */
Private Static final int pool_size = 1;
 
Private keyinfo;

/**
* Constructor.
* @ Param poolsize obtain several values each time and place them in the cache. If the value is smaller than 1, the default value is 1. <Br>
* The recommended value is 2, which means a maximum of one number is wasted each time the application is restarted, and the efficiency can be doubled. <Br>
* If the value of 1 is used, the probability of waste is the lowest. But it cannot be used in highly concurrent systems.
* @ Param keyname corresponds to the key of the maximum good table.
*/
Private keygenerator (INT poolsize, string keyname ){
If (poolsize <1 ){
Poolsize = pool_size;
}
Keyinfo = new keyinfo (poolsize, keyname );
}

/**
* Ensure thread security.
* @ Param poolsize cache size
* @ Param keyname primary key name
* @ Return
*/
Public static synchronized keygenerator getinstance (INT poolsize, string keyname ){
Keygenerator keygen;
If (kengens. containskey (keyname )){
Keygen = kengens. Get (keyname );
// System. Out. println ("Get from cache" + keyname );
} Else {
Keygen = new keygenerator (poolsize, keyname );
Kengens. Put (keyname, keygen); // register it in hashmap. Improve Efficiency
// System. Out. println ("registered" + keyname );
}
Return keygen;
}

/**
* Get the Sequence Value of the int type
* @ Return
*/
Public int getnextintkey (){
Return keyinfo. getnextintkey ();
}
/**
* Obtain the Sequence Value of the long type. It is generally not used. Unless it is like mobile China Unicom, there are hundreds of millions of calls every day.
* @ Return
*/
Public long getnextlongkey (){
Return keyinfo. getnextlongkey ();
}
/**
* Obtain the Sequence Value of the string type.
* @ Param paddinglength: returns the length of a string. The maximum length is 10 characters. If long is used, it can be up to 19 digits.
* @ Return
*/
Public String getnextstringkey (INT paddinglength ){
Return keyinfo. getnextstringkey (paddinglength );
}
}
= ====

Package com. SYS. maxnumber;

/**
* During the test, modify the retrievefromdb method of keyinfo so that it can be connected through JDBC.
* Note that the keyname must exist in the largest table!
* @ Author wangmingjie
* @ Date 2009-8-4 10:38:19 AM
*/
Public class keyclient {
// General usage, keygenerator. getinstance (1, "bugproject"). getnextintkey ();
// Increase the value of poolsize when the number of concurrent operations is large, which can reduce the number of database accesses.
 
/**
* Usage
*
* @ Param ARGs
*/
Public static void main (string [] ARGs ){
// Keygenerator keygen = keygenerator. getinstance (1, "bugproject ");
//
// For (INT I = 0; I <25; I ++ ){
// System. Out. println ("Key (" + (I + 1) + ") =" + keygen. getnextintkey ());
//}
//
// For (INT I = 0; I <25; I ++ ){
// System. Out. println ("Key (" + (I + 1) + ") =" + keygen. getnextstringkey (6 ));
//}

Threada T = new threada ();
Thread T1 = new thread (T, "");
Thread t2 = new thread (T, "B ");
Thread T3 = new thread (T, "C ");
Thread t4 = new thread (T, "D ");
T1.start ();
T2.start ();
T3.start ();
T4.start ();
// When there are too many accesses, a transaction deadlock occurs. Therefore, the number of caches must be increased in High-concurrency systems.
// Java. SQL. sqlexception: the transaction (process ID 143) and another process have been deadlocked on the lock resource, and the transaction has been selected as a deadlock victim. Run the transaction again.
// Bkey A (12) = 000137
// Threada TA = new threada ();
// Ta. Run ();
// Threadb TB = new threadb ();
// TB. Run ();

}
}
Class threada implements runnable {
Public void run (){
Keygenerator keygen = keygenerator. getinstance (1, "bugproject ");
For (INT I = 0; I <500; I ++ ){
System. Out. println (thread. currentthread (). getname () + "Key A (" + (I + 1) + ") ="
+ Keygen. getnextintkey () + "|"
+ Keygen. getnextintkey ()
+ "|"
+ Keygen. getnextstringkey (4 ));
}
}
}
Class threadb implements runnable {
Public void run (){
Keygenerator keygen = keygenerator. getinstance (1, "bugproject ");
For (INT I = 0; I <500; I ++ ){
System. out. println (thread. currentthread (). getname () + "Key B (" + (I + 1) + ") =" + keygen. getnextstringkey (6 ));
}
}
}
================ Pojo ============================

Package com. SYS. model;

Import java. Io. serializable;

/**
*
*/

Public class maxnumber implements serializable {

// Constructors
Public maxnumber (){

}

/**
* Constructor for primary key
*/
Public maxnumber (string ID ){
This. setid (ID );

}

// Primary key
Private string ID; // ID

 

Public java. Lang. String GETID (){
Return ID;
}

Public void setid (string ID ){
This. ID = ID;
}

Private string keyname; // primary key
Private integer keyValue; // Value
Private string remark; // remarks

Public String getkeyname (){
If (keyname = NULL) return NULL;
Else return keyname. Trim ();
}

Public void setkeyname (string keyname ){
This. keyname = keyname;
}
Public integer getkeyvalue (){
Return keyValue;
}

Public void setkeyvalue (integer keyValue ){
This. keyValue = keyValue;
}
Public String getremark (){
If (Remark = NULL) return NULL;
Else return remark. Trim ();
}

Public void setremark (string remark ){
This. remark = remark;
}

/* (Non-javadoc)
* @ See java. Lang. Object # hashcode ()
*/
@ Override
Public int hashcode (){
Final int prime = 31;
Int result = super. hashcode ();
Result = prime * result + (ID = NULL )? 0: Id. hashcode ());
Return result;
}

/* (Non-javadoc)
* @ See java. Lang. Object # equals (Java. Lang. Object)
*/
@ Override
Public Boolean equals (Object OBJ ){
If (this = OBJ)
Return true;
If (! Super. Equals (OBJ ))
Return false;
If (getclass ()! = Obj. getclass ())
Return false;
Final maxnumber Other = (maxnumber) OBJ;
If (ID = NULL ){
If (other. ID! = NULL)
Return false;
} Else if (! Id. Equals (other. ID ))
Return false;
Return true;
}

Public String tostring (){
Stringbuffer sb = new stringbuffer ("");
SB. append ("maxnumber {id ="); sb. append (ID); sb. append (",");
SB. append ("keyname ="); sb. append (keyname); sb. append (",");
SB. append ("keyValue ="); sb. append (keyValue); sb. append (",");
SB. append ("remark ="); sb. append (remark );
SB. append ("}");
Return sb. tostring ();
}

 

}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.