public class SequenceUtil {
private static Logger logger = LoggerFactory.getLogger(SequenceUtil.class);
/** 存当前不同类型ID值 **/
private static HashMap<String, SequenceInfo> currSeqMap = new HashMap<String, SequenceInfo>();
/**ID_COMMON*/
private static String ID_COMMON ="ID_COMMON";
/***
* <b>说明:</b> 获取表唯一ID,为19位字符,(表类型3位+日期6位+数据库sequence 6位+内存自增记数4位)
*
* @param
* @return
* @author costin_law
* @since 2014年5月26日
*/
public static String getId(UniqueIdCode idCode) {
StringBuffer strBuff = new StringBuffer(19);
if(StringUtils.isBlank(idCode.getCode()) || (2 != idCode.getCode().length() && 3 != idCode.getCode().length())){
throw new IllegalArgumentException("uniqueIdCode format error");
}
if(2 == idCode.getCode().length()){
strBuff.append("C").append(idCode.getCode()); // +3
}else{
strBuff.append(idCode.getCode()); // +3
}
strBuff.append(DateUtil.getCurDate(DateUtil.DATE_FROMAT_YYMMDD)); // +6
String sequenceName = idCode.getSequenceName();
if(StringUtils.isBlank(sequenceName)){
sequenceName = ID_COMMON;
}
long value = getNextValue(sequenceName,4);
strBuff.append(StringFillUtil.LeftFill(String.valueOf(value), '0', 10));
return strBuff.toString();
}
/***
* 根据指定的sequenceCode 获取序列值
*
* @param sequenceCode
* @param size
* 缓存到内存中的位数
* @return long
* @author costin_law
*
*/
protected static long getNextValue(String idType,int size) {
long intPow = (long) Math.pow(10, size);
SequenceInfo sequenceInfo = currSeqMap.get(idType);
if (sequenceInfo == null ) {
synchronized(currSeqMap){
sequenceInfo = currSeqMap.get(idType);
if( sequenceInfo == null){
sequenceInfo = new SequenceInfo();
currSeqMap.put(idType,sequenceInfo);
}
}
}
long seqValue = sequenceInfo.seqNo.incrementAndGet();
long oldDbSeq = sequenceInfo.dbSeq;
//如果判断当前号段是否用完,用完则从数据库取新号段
while( seqValue >= intPow || oldDbSeq <= 0 ){
synchronized (sequenceInfo) {
if( oldDbSeq == sequenceInfo.dbSeq ){
sequenceInfo.dbSeq = getDbSeqValue(idType);
seqValue = 1;
sequenceInfo.seqNo.set(seqValue);
}else{
seqValue = sequenceInfo.seqNo.incrementAndGet();
}
oldDbSeq = sequenceInfo.dbSeq;
}
}
return (oldDbSeq * intPow) + seqValue;
}
/**
* <b>说明:</b> 根据指定的序列值获取值
*
* @param
* @return
* @throws ServiceException
* @author costin_law
*
*/
private static long getDbSeqValue(String idType) {
/*DataSource dataSource = (DataSource) SpringContextHolder.getBean("dataSource");
OracleSequenceMaxValueIncrementer sequence = new OracleSequenceMaxValueIncrementer();
sequence.setDataSource(dataSource);
sequence.setIncrementerName(sequenceCode.getCode());*/
SequenceDao sequenceDao = SpringContextHolder.getBean("sequenceDao");
try {
return sequenceDao.getSequenceValue(idType);
} catch(Exception e1) {
for (int i=0; i<3; i++) {
try {
Random random=new Random();
long randomMs = random.nextInt(1001)+1000;
Thread.sleep(randomMs);
return sequenceDao.getSequenceValue(idType);
} catch(Exception e2) {
logger.error("第" + i + "次获取失败");
}
}
throw e1;
}
}
static class SequenceInfo{
long dbSeq = -1;
AtomicLong seqNo = new AtomicLong(-1);
}
}
@Service("sequenceDao")
public class SequenceDao {
private static Logger logger = LoggerFactory.getLogger(SequenceDao.class);
private void updateSequence(Connection connection, String sequenceName, Map<String,Long> resultMap) throws SQLException {
PreparedStatement ps = null;
try {
ps = connection.prepareStatement("UPDATE SMY.SEQUENCE_INFO set SEQUENCE_VALUE=?,UPDATE_TIME=NOW() WHERE SEQUENCE_NAME=? AND SEQUENCE_VALUE=?");
long seqCurrValue = resultMap.get("seqCurrValue");
long maxValue = resultMap.get("maxValue");
long seqLen = resultMap.get("seqLen");
long increment = resultMap.get("increment");
long startValue = resultMap.get("startValue");
long seqNextValue = seqCurrValue + increment;
if (seqNextValue >= maxValue || seqNextValue > (Math.pow(10, seqLen) - 1)) {
seqNextValue = startValue;
}
ps.setLong(1, seqNextValue);
ps.setString(2, sequenceName);
ps.setLong(3, seqCurrValue);
int cnt = ps.executeUpdate();
logger.debug("更新流水号[{}],参数{}", sequenceName, seqNextValue);
if (cnt != 1 || ps.getUpdateCount() != 1) {
logger.error("更新流水号[{}]信息失败,返回更新记录数{}", sequenceName, cnt);
throw new RuntimeException("update sequence error[" + sequenceName + "]");
}
} finally {
if (ps != null) {
ps.close();
}
}
}
private void insertSequence(Connection connection, String sequenceName) throws SQLException {
PreparedStatement ps = null;
try {
ps = connection.prepareStatement("INSERT INTO SMY.SEQUENCE_INFO (SEQUENCE_NAME,SEQUENCE_VALUE,MAX_VALUE,SEQUENCE_LEN,INCREMENT,START_VALUE) VALUES(?,?,?,?,?,?)");
ps.setString(1, sequenceName);
ps.setLong(2, 10);
ps.setLong(3, 999999);
ps.setInt(4, 6);
ps.setInt(5, 1);
ps.setInt(6, 10);
ps.execute();
logger.debug("新增流水号[{}],成功", sequenceName);
} finally {
if (ps != null) {
ps.close();
}
}
}
private Map<String,Long> querySequence(Connection connection, String sequenceName) throws SQLException {
PreparedStatement ps = null;
ResultSet rs = null;
Map<String,Long> resultMap = new HashMap<String,Long>();
try {
logger.debug("开始从数据库取分段流水[" + sequenceName + "]");
ps = connection.prepareStatement("SELECT SEQUENCE_VALUE, MAX_VALUE, SEQUENCE_LEN, INCREMENT, START_VALUE " + " from SMY.SEQUENCE_INFO where SEQUENCE_NAME=? ");
ps.setString(1, sequenceName);
rs = ps.executeQuery();
if (rs.next()) {
long seqCurrValue = rs.getLong(1);
long maxValue = rs.getLong(2);
long seqLen = rs.getLong(3);
long increment = rs.getLong(4);
long startValue = rs.getLong(5);
resultMap.put("seqCurrValue",seqCurrValue);
resultMap.put("maxValue", maxValue);
resultMap.put("seqLen", seqLen);
resultMap.put("startValue", startValue);
resultMap.put("increment", increment);
logger.debug("取分段流水[" + sequenceName + "]完成");
return resultMap;
} else {
resultMap.put("seqCurrValue",-1L);
return resultMap;
}
} finally {
if (rs != null) {
rs.close();// 释放数据库锁
}
if (ps != null) {
ps.close();
}
}
}
@Transactional(propagation=Propagation.REQUIRES_NEW)
public long getSequenceValue(String sequenceName) {
SqlSessionFactory sqlSessionFactory = SpringContextHolder.getBean("sqlSessionFactory");
SqlSession sqlSession = sqlSessionFactory.openSession(false);
Connection conn = sqlSession.getConnection();
try {
// openSession指定autoCommit=false不起作用, 只对通过session的方法执行的有效,只能自己再设置一次
conn.setAutoCommit(false);
} catch (SQLException e) {
logger.error("关闭连接自动事务提交异常!");
}
try {
Map<String, Long> resultMap = querySequence(conn, sequenceName);
long seqCurrValue = resultMap.get("seqCurrValue");
//没找到,就新增sequence
if(seqCurrValue == -1){
insertSequence(conn, sequenceName);
resultMap = querySequence(conn, sequenceName);
seqCurrValue = resultMap.get("seqCurrValue");
}
updateSequence(conn, sequenceName, resultMap);
conn.commit();
return seqCurrValue;
} catch (SQLException sqlE) {
logger.warn("取分段流水出现异常,流水名称:{}.", sequenceName, sqlE);
throw new RuntimeException("obtain sequence error[" + sequenceName + "]");
} finally {
sqlSession.close();
}
}
}