Sử dụng trigger trong SQL Generrate mã code kết hợp một String + id Auto Increament.

Thông tin chi tiết về bài toán:

Ở đây tôi có một bài toán từ khách hàng như sau: Hãy tạo cho tao một mã đơn hàng (trans_confirm_no) để tao có thể phân biệt được các đơn hàng với nhau với định dạng như này “TMSxxxxx” và nó sẽ phải bắt đầu từ “TMS00001“.


Ngay khi nhận được yêu cầu thì tôi đã bắt tay ngay vào việc code và ngôn ngữ tôi sử dụng cho dự án này là Java spring boot và MSQL.

Cách sử dụng code để generate mã trans_confirm_no

Java
// hàm tạo ra mã trans_confirm_no mới tăng dần
private synchronized String getTransConfirmNoDiorTest(){
        String maxTransConfirmNo = transactionDiorMapper.getTransConfirmNo();
        log.info("maxTransConfirmNo: {}", maxTransConfirmNo);
        StringBuilder result = new StringBuilder();
        if (StringUtils.isBlank(maxTransConfirmNo)){
            logger.warn("Order transConfirmNo failed, transConfirmNo={}", maxTransConfirmNo);
            result.append("00001");
        } else {
            int maxTransConfirmNoIntValue = Integer.parseInt(maxTransConfirmNo.substring(3)) + 1;
            if (maxTransConfirmNoIntValue > 0 && maxTransConfirmNoIntValue < 100000 ) {
                int len = 5 - ((Integer)maxTransConfirmNoIntValue).toString().length();
                if ( len > 0 ) {
                    for (int i = 0; i < len ; i++) {
                        result.append("0");
                    }
                    result.append(maxTransConfirmNoIntValue);
                } else {
                    result.append(maxTransConfirmNoIntValue);
                }
            } else {
                result.append("00001");
            }
        }
        log.info("result: {}", result);
        return "TMS" + result;
    }
Java
 // hàm lấy ra mã trans_confirm_no lớn nhất đang có
 SELECT
            ttd.trans_confirm_no
        FROM
            t_transaction_dior ttd
        WHERE
            ttd.delete_flag = 0
            AND ttd.trans_confirm_no LIKE 'JPD%'
            AND ttd.trans_status IS NOT NULL
        ORDER BY ttd.trans_confirm_no DESC
        LIMIT 1;

Vấn đề gặp phải ở đây là khi chúng tôi có nhiều đầu api call đến hàm này cùng thời điểm thì việc tạo ra một mã TMSxxxxx tăng dần gặp vấn đề và nó Generate không đúng với mong muốn.

Khi hệ thống có lượng truy cập lớn, số lượng user mua hàng dồn dập, hàm bên trên sẽ xảy ra trường hợp sinh ra các mã trans_confirm_no trùng nhau.

Sử dụng trigger generate mã trans_confirm_no

Java
// Đầu tiên chúng ta tạo ra 1 bảng để sử cơ chế AUTO_INCREMENT trong mysql để  lấy được phần xxxxx nằm trong fomat "TMSxxxxx"
CREATE TABLE transaction_seq
(
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);

// Mình tạo ra 1 trigger sử dụng concat để nối prefix TMS + xxxxx đã được gen ở bảng transaction_seq phía trên.
DELIMITER $$
CREATE TRIGGER tg_t_transaction_dior_insert
    BEFORE INSERT ON t_transaction_dior
    FOR EACH ROW
BEGIN
    INSERT INTO transaction_seq VALUES (NULL);
    SET NEW.trans_confirm_no = CONCAT('TMS', LPAD(LAST_INSERT_ID(), 5, '0'));
END$$
    DELIMITER ;

// Đặt giá trị bắt đầu AUTO_INCREMENT trong table transaction_seq
ALTER TABLE transaction_seq AUTO_INCREMENT=00001;

Khi sử dụng trigger đã giải quyết được vấn đề của tôi trong bài toán này.

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like