zoukankan      html  css  js  c++  java
  • 自定义流水号的autocode

    package cn.com.do1.component.yopin.util;

    import cn.com.do1.common.dac.QuickDAC;
    import cn.com.do1.common.exception.BaseException;
    import cn.com.do1.common.util.AssertUtil;
    import cn.com.do1.dqdp.core.DqdpAppContext;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    import javax.sql.DataSource;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Map;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;


    /**
    *
    * 自动编码工具类 <br/>调用 AutoCodeUtil.getAutoCode("传入编码前缀字符串")
    * @author ao.ouyang
    * 2015-4-23 10:00:17
    */
    public final class AutoCodeUtil {
    private final static Logger log = LoggerFactory.getLogger(AutoCodeUtil.class);
    private final static ThreadLocal<Integer> executeCount = new ThreadLocal<Integer>(){
    @Override
    protected Integer initialValue() {
    return 1;
    }
    };
    private static DataSource ds;
    private static AutoCodeUtil util;
    private final static Lock lock = new ReentrantLock(true);

    private AutoCodeUtil() {
    ds = DqdpAppContext.getSpringContext().getBean(DataSource.class);
    }

    public static AutoCodeUtil getInstance() {
    if (null == util) {
    lock.lock();
    try {
    util = new AutoCodeUtil();
    } finally {
    lock.unlock();
    }
    }
    return util;
    }

    /**
    * 这个方法不能直接调用,因为没有加锁来控制并发
    * @param type
    * @return
    * @throws BaseException
    */
    private long getCurrentVal(String type) throws BaseException {
    try {
    Connection conn = ds.getConnection();
    QuickDAC dac = null;
    try {
    dac = new QuickDAC(conn);
    dac.preparedSql("select BEGINNING_VAL,INCREASE_STEP,CURRENT_VAL from tb_sequence t where t.val_type = UCASE(:type)");
    dac.setPreValue("type", type);
    Map<String, Long> query = dac.executeQuery();
    if (!AssertUtil.isEmpty(query)) {
    dac.preparedSql("update tb_sequence set current_val = case when current_val + increase_step > beginning_val then current_val + increase_step else beginning_val end where val_type = UCASE(:type)");
    dac.setPreValue("type", type);
    dac.executeUpdate();
    return Math.max(query.get("CURRENT_VAL") + query.get("INCREASE_STEP"), query.get("BEGINNING_VAL"));
    } else {
    dac.preparedSql("insert into tb_sequence(val_type,current_val) values(UCASE(:type), :val)");
    dac.setPreValue("type", type).setPreValue("val", 1);
    dac.executeUpdate();
    log.info("创建新的类别流水号:{}", type);
    return 1L;
    }
    } finally {
    if (null != dac)
    dac.destoryWithoutConnection();
    if (null != conn)
    conn.close();
    }
    } catch (SQLException e) {
    throw new BaseException(String.format("获取%s系统流水号失败", type), e);
    }
    }

    private long getCurrentValAndLock(String type) throws BaseException {
    try {
    if (lock.tryLock(30, TimeUnit.MILLISECONDS)) {
    try {
    executeCount.set(0);
    return this.getCurrentVal(type);
    } finally {
    lock.unlock();
    }
    } else {
    log.warn("在指定的时间内未能获取指定类别的流水号:{}", type);
    if (5 <= executeCount.get()) {
    log.error("系统连续5次获取指定类别的流水号失败:{}", type);
    return -1L;
    }
    executeCount.set(executeCount.get() + 1);
    return getCurrentValAndLock(type);
    }
    } catch (InterruptedException e) {
    throw new BaseException(e);
    }
    }

    /**
    * 流水号开头,不包括type这个类别标识,生成的流水号:00000002321
    * @param type
    * @param length
    * @return
    * @throws BaseException
    */
    private String currentSequence(String type, int length) throws BaseException {
    long value = getInstance().getCurrentValAndLock(type);
    StringBuilder sb = new StringBuilder("0000000000000000000");
    sb.append(value); //sb=00000000000000000001234567
    sb.reverse(); //sb=76543210000000000000000000
    sb.setLength(length); //sb=7654321000
    return sb.reverse().toString(); //sb=0001234567
    }

    /**
    * 按照指定类别名称,获取当前流水号,返回的流水号开头显示类别名称
    * @param type 流水类别名称
    * @return
    * @throws BaseException
    */
    public String currentSequence(String type) throws BaseException {
    SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHH");
    return type + sdf.format(new Date()) + this.currentSequence(type, 5);
    }

    /**
    * 按默认类别获取当前的流水号,返回的流水号开头不显示类别名称
    * @return
    * @throws BaseException
    */
    public String currentSequence() throws BaseException {
    SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHH");
    return sdf.format(new Date()) + this.currentSequence("default", 8);
    }
    }
  • 相关阅读:
    最小生成树之算法记录【prime算法+Kruskal算法】【模板】
    hdoj 1869 六度分离【最短路径求两两边之间最长边】
    la3211
    codeforces round #414 div1+div2
    bzoj1823
    bzoj3112
    bzoj1061&&bzoj3256
    单纯形&&线性规划
    bzoj1494
    bzoj3105
  • 原文地址:https://www.cnblogs.com/signheart/p/6597931.html
Copyright © 2011-2022 走看看