最近又遇到须要根据日期生成流水号的业务,而后记录了几种生成方法,一个是经过java代码,一个是数据库的触发器,还有是经过redis。下面是代码: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');
主要利用 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