java,mysql觸發器,redis生成流水號(yyyyMM000)

最近又遇到須要根據日期生成流水號的業務,而後記錄了幾種生成方法,一個是經過java代碼,一個是數據庫的觸發器,還有是經過redis。下面是代碼:java

經過java生成簡易流水:

/**
     * 經過日期和生成的流水號拼接
     * @param maxCount 已經生成的個數
     * @return
     */
    public static String recountNew(int maxCount) {
        if (maxCount < 0) {
            return null;
        }
        //201707999
        String str = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMM"));
        String countStr = str + num(maxCount, 3, 3);
        System.out.println("合同編號: " + Long.valueOf(countStr));
        return countStr;
    }

    /**
     * 生成流水號
     * @param current 當前生成個數
     * @param max 最大整數位
     * @param min 最小整數位
     * @return 生成的流水號
     */
    public static String num(int current, int max, int min) {
        current++;
        NumberFormat numberFormat = NumberFormat.getInstance();
        //設置是否使用分組
        numberFormat.setGroupingUsed(false);
        //設置最大整數位數
        numberFormat.setMaximumIntegerDigits(max);
        //設置最小整數位數
        numberFormat.setMinimumIntegerDigits(min);
        return numberFormat.format(current);
    }

經過數據觸發器實現:

主要邏輯:以201906001 爲例,根據當前日期 201606 獲取流水號最大的一個,保存到n。而後把流水號加1,再和當前日期201906拼接到一塊兒git

CREATE TABLE orders (
            orders_id INT (10) PRIMARY KEY,
            customer_name VARCHAR (100)
        );

        DROP TRIGGER tr_orders_id;

        CREATE TRIGGER tr_orders_id BEFORE INSERT ON orders FOR EACH ROW
        BEGIN
            DECLARE
                n INT;
        SELECT
            IFNULL(max(RIGHT(orders_id, 3)), 0) INTO n
        FROM
            orders
        WHERE
            mid(orders_id, 1, 6) = DATE_FORMAT(now(), '%Y%m');
        SET NEW.orders_id = concat(
            DATE_FORMAT(now(), '%Y%m'),
            RIGHT (001 + n, 3)
        );
        END;

        INSERT INTO orders VALUES (0, 'jack');
        INSERT INTO orders VALUES (0, 'jack');

redis實現(採用)

主要利用 StringRedisTemplate 來操做redis,寫在業務層,須要使用直接注入就行。這是沒有詳細的說明配置StringRedisTemplate,下面代碼會有問題,只是知道有這個方法,有用的時候,本身去寫一下就行了。redis

/**
 * @version V1.0
 * @Authoer CX
 * @Since:2019/5/20
 */
public interface NumberGenService {

    /**
     * 根據code生成編號
     * 例:NB000001
     * @param code 前綴
     * @return 編號
     */
    String generateNumber(String code);

    /**
     * 根據code及年月生成編號
     * 例子:NB201905000001
     * @param code 前綴
     * @return 編號
     */
    String generateNumberByMonth(String code);


    /**
     * 根據code及年月生成編號
     * 例子:NB20190508000001
     * @param code 前綴
     * @return 編號
     */
    String generateNumberByDay (String code);
}
import com.cloudkeeper.confinement.main.service.NumberGenService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @version V1.0
 * @Authoer CX
 * @Since:2019/5/20
 */
@Service
public class NumberGenServiceImpl implements NumberGenService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static final int LENGTH = 6;

    private static final String MONTH_FORMAT = "yyyyMM";

    private static final String DAY_FORMAT = "yyyyMMdd";

    public String generateNumber (String code) {
        return getNumber(code, "");
    }

    public String generateNumberByMonth (String code) {
        return getNumber(code, new SimpleDateFormat(MONTH_FORMAT).format(new Date()));
    }

    public String generateNumberByDay (String code) {
        return getNumber(code, new SimpleDateFormat(DAY_FORMAT).format(new Date()));
    }


    private String getNumber(String code, String month) {
        code += month;
        Long number = stringRedisTemplate.opsForValue().increment("" + ":" + code);
        return code + StringUtils.leftPad(number.toString(), LENGTH, '0');
    }

}

總結

以上是總結的幾種實現方式,公司採用的是經過redis的自增來實現的,能夠避免併發時生成相同編號的問題。經過java生成,在保存時會出現相同編號的問題。spring

相關文章
相關標籤/搜索