电子商务订单号生成对策

电子商务订单号生成策略
一般采用: 时间+序列号

20111001+000001 = 20111001000001
规则 : 前面以年月日前缀+序列号每天从1天始 第二天又是从1开始

代码:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.sql.DataSource;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.batch.item.database.support.DefaultDataFieldMaxValueIncrementerFactory;
import org.springframework.batch.support.DatabaseType;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;

public class DailyRollingIncrementer implements InitializingBean {

/**
* define bean as :
* <bean id="dailyRollingIncrementer" class="com.book511.incrementer.DailyRollingIncrementer">
*   <property name="dataSource" ref="dataSource"/>
*   <property name="incrementerName" value="TEST_SEQ"/>
*  </bean>

*  and run sql in MySQL as :
*  CREATE TABLE TEST_SEQ (ID BIGINT NOT NULL) ENGINE=MYISAM;
*  INSERT INTO TEST_SEQ(id) select 0 from DUAL where not exists (select id from TEST_SEQ);
*  CREATE TABLE TEST_SEQ_ROLLING (`YMD` CHAR(8) NOT NULL , `SEQ_NUMBER` BIGINT NULL , PRIMARY KEY (`YMD`) ) ENGINE = MyISAM;

*/
private String incrementerName;

private DataSource dataSource;

private DefaultDataFieldMaxValueIncrementerFactory maxValueIncrementerFactory;

private DataFieldMaxValueIncrementer maxValueIncrementer;

private String rollingTable;


private String selectSql;

private String insertSql;

private String currentYmd = null;

private Long currentSeq = null;

private DateTimeFormatter formatter = DateTimeFormat.forPattern("YYYYMMdd");

/**
* Caution !!!
* you should check if return value is not 0
* @return
*/
public long nextLongValue() {
DateTime dt = new DateTime();
String ymd = formatter.print(dt);
return nextLongValue(ymd);
}


public synchronized long nextLongValue(String ymd) {
Long nextSeq = 0L;
try {
nextSeq = maxValueIncrementer.nextLongValue();
System.out.println("nextSeq is : " + nextSeq);
} catch (Exception e) {
return 0L;
}
long number = seqNumber(ymd);
if (number == 0) {
number = nextSeq;
insertSeqNumber(ymd, number);
/*try {
Thread.sleep(10000);
} catch (InterruptedException e) {
}*/
}
return nextSeq - number + 1;
}

private synchronized long seqNumber(String ymd) {
if (ymd != null) {
if (ymd.equals(currentYmd))
return currentSeq;
}
Connection con = null;
PreparedStatement selectPreparedStatement = null;
try {
con = DataSourceUtils.getConnection(getDataSource());
selectPreparedStatement = con.prepareStatement(selectSql);
DataSourceUtils.applyTransactionTimeout(selectPreparedStatement,
getDataSource());
selectPreparedStatement.setString(1, ymd);
ResultSet rs = selectPreparedStatement.executeQuery();
if (rs.next()) {
long seq = (long) rs.getLong(1);
currentYmd = ymd;
currentSeq = seq;
return seq;
}
} catch (Exception ex) {
// throw new DataAccessResourceFailureException(
// "Error ...", ex);
} finally {
JdbcUtils.closeStatement(selectPreparedStatement);
DataSourceUtils.releaseConnection(con, getDataSource());
}
return 0;
}

private synchronized boolean insertSeqNumber(String ymd, long seqNumber) {
Connection con = null;
PreparedStatement selectPreparedStatement = null;
try {
con = DataSourceUtils.getConnection(getDataSource());
PreparedStatement insertPreparedStatement = con
.prepareStatement(insertSql);
insertPreparedStatement.setString(1, ymd);
insertPreparedStatement.setLong(2, seqNumber);
int count = insertPreparedStatement.executeUpdate();
System.out.println("count is : " + count);
return count > 0;
} catch (Exception ex) {
System.out.println("seqNumber = " + seqNumber);
ex.printStackTrace();
} finally {
JdbcUtils.closeStatement(selectPreparedStatement);
DataSourceUtils.releaseConnection(con, getDataSource());
}
return false;
}

public String genSn(int bit){
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Date dNow = new Date();
String dateStr = sdf.format(dNow).toString();
long v = nextLongValue(dateStr);
String v_s = String.valueOf(v);
int num = getNumBit(v_s);
if(num<bit){
int zeroNum = bit - num;
String zeroStr = "";
for(int i=0;i<zeroNum;i++){
zeroStr += "0";
}
System.out.println("result is : " + zeroStr);
v_s = zeroStr + v_s;
}
if(v_s.length()!=bit){
System.out.println("error");
}
return v_s;
}

public int getNumBit(String str){
if(str!=null){
str = str.trim();
}
int numlen=0;
        for (int i=0;i<str.length();i++){
            System.out.print(str.substring(i, i+1)+",");//substring把STR的每一个字符取出
            numlen++;//计数
        }
return numlen;
}


@Override
public void afterPropertiesSet() throws Exception {
DatabaseType incrementerType = DatabaseType.fromMetaData(dataSource);
maxValueIncrementerFactory = new DefaultDataFieldMaxValueIncrementerFactory(
dataSource);
maxValueIncrementer = maxValueIncrementerFactory.getIncrementer(
incrementerType.getProductName(), incrementerName);
rollingTable = incrementerName + "_ROLLING";
selectSql = "select SEQ_NUMBER from " + rollingTable + " where YMD = ?";
insertSql = "insert into " + rollingTable + "(YMD,SEQ_NUMBER) values(?,?)";
}

public String getIncrementerName() {
return incrementerName;
}

public void setIncrementerName(String incrementerName) {
this.incrementerName = incrementerName;
}

public DataSource getDataSource() {
return dataSource;
}

public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}

}