huang
4 天以前 9571229a2013472dc701ecf5767f2873b36d8f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.mes.device.service.impl;
 
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mes.device.entity.EngineeringSequence;
import com.mes.device.mapper.EngineeringSequenceMapper;
import com.mes.device.service.EngineeringSequenceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
 
/**
 * 工程序号信息服务实现类
 *
 * @author mes
 * @since 2025-11-20
 */
@Slf4j
@Service
public class EngineeringSequenceServiceImpl extends ServiceImpl<EngineeringSequenceMapper, EngineeringSequence> implements EngineeringSequenceService {
 
    // 修复:使用ThreadLocal保证DateTimeFormatter的线程安全
    private static final ThreadLocal<DateTimeFormatter> DATE_FORMATTER_THREAD_LOCAL = ThreadLocal.withInitial(
            () -> DateTimeFormatter.ofPattern("yyMMdd")
    );
 
    // 重试间隔(毫秒),使用随机数避免并发请求同时重试
    private static final int RETRY_INTERVAL_MIN = 50;
    private static final int RETRY_INTERVAL_MAX = 200;
 
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String generateAndSaveEngineeringId(Date date) {
        try {
            Integer maxSequence = baseMapper.selectMaxSequenceByDate(date);
            maxSequence = (maxSequence == null) ? 0 : maxSequence;
            int newSequence = maxSequence + 1;
 
            LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            String dateStr = DATE_FORMATTER_THREAD_LOCAL.get().format(localDate);
            String engineeringId = "P" + dateStr + String.format("%02d", newSequence);
 
            EngineeringSequence engineeringSequence = new EngineeringSequence();
            engineeringSequence.setEngineeringId(engineeringId);
            engineeringSequence.setDate(date);
            engineeringSequence.setSequence(newSequence);
            engineeringSequence.setCreatedTime(new Date());
            engineeringSequence.setUpdatedTime(new Date());
            engineeringSequence.setCreatedBy("system");
            engineeringSequence.setUpdatedBy("system");
 
            save(engineeringSequence);
 
            log.info("生成工程号成功: engineeringId={}, date={}, sequence={}", engineeringId, date, newSequence);
            return engineeringId;
        } catch (DuplicateKeyException dup) {
            log.error("生成工程号唯一键冲突: date={}", date, dup);
            throw new RuntimeException("生成工程号失败", dup);
        } catch (Exception e) {
            log.error("生成工程号失败, date={}", date, e);
            throw new RuntimeException("生成工程号失败", e);
        }
    }
}