天天看點

編号功能

基礎知識:相關注解:

@RequestBody(required = true) 這個注解一般就是前端需要傳入一個對象

@RequestParam(required = true)這個注解一般就是前端需要傳入某些字段

業務需求:自定義編碼規則.設計一個由 字首+字尾+時間戳+序列前置字元+自增序列 組成的編号規則,時間戳的位置可變.

涉及的資料庫表有hr_serial_num_info------編碼資訊表;hr_serial_num_relation------編碼關聯表;sequence------自增序号表;

項目層級結構:

編号功能

接口:增删改查:

1.編号資訊新增修改

(1)controller層 ----SerialNumRestController

/**
 1. 編号資訊新增/修改
 2.  3. @param serialNumInfo
 4. @return
 */
@PostMapping(value = "/doSave")
@ApiOperation(value = "新增/修改編号資訊")
@ApiImplicitParam(value = "編号資訊DTO", name = "serialNumInfo")
@ResponseBody
public ResponseMessage doSave(@RequestBody(required = true) SerialNumInfoDTO serialNumInfo) {
    /* try {*/
    return serialNumService.doSave(serialNumInfo);
   /* } catch (Exception e) {
        return Result.error("操作失敗");
    }
    */
}
           
(2)service層----SerialNumServicel 我把邏輯代碼都放到了這個service實作類中
/**
 * 編号資訊新增/修改
 * @param serialNumInfoDTO
 * @return
 */
ResponseMessage doSave(SerialNumInfoDTO serialNumInfoDTO);
           
service層----SerialNumInfoService
public interface SerialNumInfoService extends IService<SerialNumInfoModel>{
}
           

(3)service層實作類

SerialNumServiceImpl

/**
     * 編号資訊新增/修改
     *
     * @param serialNumInfoDTO
     * @return
     */
    @Override
    public ResponseMessage doSave(SerialNumInfoDTO serialNumInfoDTO) {
        //建立一個infomodel對象,用來向資料庫存入資料
        SerialNumInfoModel serialNumInfoModel = new SerialNumInfoModel();
        //調用corvet方法,轉存資料
        corvet(serialNumInfoDTO, serialNumInfoModel);//調用corvet方法,轉存資料
        BeanUtils.copyProperties(serialNumInfoDTO, serialNumInfoModel);
        //判斷info表中Id是否已經存在
        if (StringUtils.isEmpty(serialNumInfoModel.getId())) {
            //資料庫編号加了索引,判斷編号是否重複
            try {
                //id不存在,新增編号資訊
                infoService.save(serialNumInfoModel);
                return ResponseMessage.ok("新增成功");
            } catch (DuplicateKeyException exception) {
                return ResponseMessage.error("編号已存在,請重新輸入");
            }
        }
        //id 已存在時,修改編号資訊
        else {
            infoService.updateById(serialNumInfoModel);
            return ResponseMessage.ok("修改成功");
        }
    }
    //此方法用來轉存資料,在編号新增接口中有調用
    private void corvet(SerialNumInfoDTO serialNumInfoDTO, SerialNumInfoModel serialNumInfoModel) {
        serialNumInfoModel.setCode(serialNumInfoDTO.getCode());
        serialNumInfoModel.setName(serialNumInfoDTO.getName());
        serialNumInfoModel.setPreString(serialNumInfoDTO.getPreString());
        serialNumInfoModel.setLastString(serialNumInfoDTO.getLastString());
        serialNumInfoModel.setTimeFormat(serialNumInfoDTO.getTimeFormat());
        serialNumInfoModel.setTimeLocation(serialNumInfoDTO.getTimeLocation());
    }
           
SerialNumInfoServiceImpl 這裡的繼承是mybatisPlus的特性,封裝了一些基本的方法.(不知道了解的對不對)
@Service
@Slf4j
public class SerialNumInfoServiceImpl extends ServiceImpl<ServialNumInfoMapper, SerialNumInfoModel> implements SerialNumInfoService {
}
           
(4)Mapper層,也用到了mybatisPlus的簡化
@Mapper
public interface ServialNumInfoMapper extends BaseMapper<SerialNumInfoModel> {
   /* List<Map<String, Object>> selectByCode(String code);*/
}
           
(5)DTO層,這一層就是對外暴露的一些字段,然後不能和資料庫字段一緻,會有安全問題.這層就不貼代碼了.至此,編号的新增修改接口就完成了.

2.建立編号關聯對象

(1)controller 層-----SerialNumRestController

/**
     * 建立編号對象關聯
     *
     * @param serialNumRelationDTO
     * @return
     */
    @PostMapping(value = "/createRelation")
    @ApiOperation(value = "建立編号對象關聯")
    @ApiImplicitParam(value = "編号對象關聯DTO", name = "serialNumRelation")
    @ResponseBody
    public ResponseMessage createRelation(@RequestBody(required = true) SerialNumRelationDTO serialNumRelationDTO) {
        return serialNumService.createRelation(serialNumRelationDTO);
    }
           
(2)service層-下面的service層代碼不再說明在哪個類中
----SerialNumServicel
/**
	 * 建立編号對象關聯
	 * @param serialNumRelationDTO
	 * @return
	 */
	ResponseMessage<SerialNumRelationDTO> createRelation(SerialNumRelationDTO serialNumRelationDTO);
           
----SerialNumRelationService
public interface SerialNumRelationService extends IService<SerialNumRelationModel>{
}
           
(3)service層實作類

這裡的業務邏輯相對多一些,需要多思考

/**
     * 建立/修改編号對象關聯
     *
     * @param serialNumRelationDTO
     * @return
     */
    @Override
    public ResponseMessage createRelation(SerialNumRelationDTO serialNumRelationDTO) {
        //建立一個relationModel 對象,用來接DTO傳過來的資料
        SerialNumRelationModel serialNumRelationModel = new SerialNumRelationModel();
        //建立sequence對象,往sequence表中加資料
        SequenceModel sequenceModel = new SequenceModel();
        //将dto的資料存到entity中
        BeanUtils.copyProperties(serialNumRelationDTO, serialNumRelationModel);
        serialNumRelationModel.setSerialId(serialNumRelationDTO.getSerialNumInfo().getId());
        //往sequence中加資料
        sequenceModel.setName(serialNumRelationDTO.getSequenceName());
        sequenceModel.setCurrentValue(serialNumRelationDTO.getStartNum());
        //資料庫中給code 加了唯一索引,在這裡是把id唯一作為條件
        if (StringUtils.isEmpty(serialNumRelationModel.getId())){
            try {
                //id不存在,新增編号關聯資訊和初始序号
                relationService.save(serialNumRelationModel);
                sequenceService.save(sequenceModel);
                return ResponseMessage.ok("新增成功");
            } catch (DuplicateKeyException exception) {
                return ResponseMessage.error("編号關聯已存在,請重新輸入");
            }
        }
        //id 已存在時,修改編号關聯資訊
        else {
            relationService.updateById(serialNumRelationModel);
            return ResponseMessage.ok("修改成功");
        }
        }
           
另一個service層實作類以及mapper層參考上面infoservice的實作類.
以下的接口代碼放到一起介紹:代碼全選粘過來的,會有上面的重複代碼.
controller層
package org.hrvc.modules.serialnum.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.hrvc.common.api.vo.ResponseMessage;
import org.hrvc.modules.serialnum.dto.SerialNumInfoDTO;
import org.hrvc.modules.serialnum.dto.SerialNumRelationDTO;
import org.hrvc.modules.serialnum.service.SerialNumRelationService;
import org.hrvc.modules.serialnum.service.SerialNumServiceI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;


/**
 * @author dongxiaomeng
 * @description controller
 * @since 2020/11/16
 */
@Api(value = "編号生成接口", tags = {"編号操作接口"})
@RestController
@RequestMapping("/test/serialNum")
@Slf4j

public class SerialNumRestController {
    @Autowired
    private SerialNumServiceI serialNumService;
    /**
     * 編号清單頁
     *
     * @return
     */
    @PostMapping(value = "/getList")
    @ApiOperation(value = "編号資訊清單")
    @ResponseBody
    public ResponseMessage<List<SerialNumInfoDTO>> getList(@RequestBody(required = true) SerialNumInfoDTO serialNumInfo) {

        /*return serialNumService.getRelationList(serialId);*/
        return serialNumService.getList(serialNumInfo);
    }

    /**
     * 編号資訊新增/修改
     *
     * @param serialNumInfo
     * @return
     */
    @PostMapping(value = "/doSave")
    @ApiOperation(value = "新增/修改編号資訊")
    @ApiImplicitParam(value = "編号資訊DTO", name = "serialNumInfo")
    @ResponseBody
    public ResponseMessage doSave(@RequestBody(required = true) SerialNumInfoDTO serialNumInfo) {
        /* try {*/
        return serialNumService.doSave(serialNumInfo);
       /* } catch (Exception e) {
            return Result.error("操作失敗");
        }
        */
    }

    /**
     * 根據主鍵id擷取編号資訊詳情
     *
     * @param id
     * @return
     */
    @PostMapping(value = "/getDetail")
    @ApiOperation(value = "根據主鍵id擷取編号資訊詳情")
    @ApiImplicitParam(value = "主鍵id", name = "id")
    @ResponseBody
    public ResponseMessage<SerialNumInfoDTO> getDetail(@RequestParam(required = true) String id) {
        return serialNumService.getDetail(id);
    }

    /**
     * 編号資訊狀态變更
     *
     * @param id
     * @param status
     */
    @PostMapping(value = "/changeStatus")
    @ApiOperation(value = "編号資訊狀态變更")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(value = "主鍵id", name = "id"),
            @ApiImplicitParam(value = "狀态", name = "status")
    })
    @ResponseBody
    public ResponseMessage<SerialNumInfoDTO> changeStatus(@RequestParam(required = true) String id, @RequestParam(required = true) int status) {
        //傳回對象,
        ResponseMessage<SerialNumInfoDTO> result = serialNumService.getDetail(id);
        //判斷傳回
        if (null == result.getResult()) {
            return ResponseMessage.error("未找到編号資訊");
        }
        try {
            serialNumService.changeStatus(id, status);

        } catch (Exception ex) {
            return ResponseMessage.error("系統異常,請稍後重試");
        }
        return result;
    }

    /**
     * 編号資訊删除
     *
     * @param id
     */
    @PostMapping(value = "/update")
    @ApiOperation(value = "編号資訊删除")
    @ApiImplicitParam(value = "主鍵id", name = "id")
    @ResponseBody
    public ResponseMessage<SerialNumInfoDTO> doDelet(@RequestParam(required = true) String id) {
        ResponseMessage<SerialNumInfoDTO> result = serialNumService.getDetail(id);
        if (null == result.getResult()) {
            return ResponseMessage.error("未找到編号資訊");
        }
        try {
            serialNumService.doDelete(id);
        } catch (Exception ex) {
            //日志
            //log.error("doDelete id={}, e={}", deleteFlag, ex);
            return ResponseMessage.error("系統異常,請稍後重試");
        }
        return ResponseMessage.ok();
    }

    /**
     * 建立編号對象關聯
     *
     * @param serialNumRelationDTO
     * @return
     */
    @PostMapping(value = "/createRelation")
    @ApiOperation(value = "建立編号對象關聯")
    @ApiImplicitParam(value = "編号對象關聯DTO", name = "serialNumRelation")
    @ResponseBody
    public ResponseMessage createRelation(@RequestBody(required = true) SerialNumRelationDTO serialNumRelationDTO) {
        return serialNumService.createRelation(serialNumRelationDTO);
    }

    /**
     * 編号對象關聯清單
     *
     * @return
     */
    @PostMapping(value = "/getRelationList")
    @ApiOperation(value = "擷取編号對象關聯清單")
    @ResponseBody
    public ResponseMessage<List<SerialNumRelationDTO>> getRelationList(String serialId) {
        return serialNumService.getRelationList(serialId);
    }

    /**
     * 擷取編号對象關聯詳情
     *
     * @param id SerialNumInfo主鍵id
     * @return
     */
    @PostMapping(value = "/getRelationDetail")
    @ApiOperation(value = "擷取編号對象關聯詳情")
    @ApiImplicitParam(value = "主鍵id", name = "id")
    @ResponseBody
    public ResponseMessage<SerialNumRelationDTO> getRelationDetail(@RequestParam(required = true) String id) {
        return serialNumService.getRelationDetail(id);
    }

    /**
     * 擷取目前編号
     *
     * @param relationObj 關聯對象
     * @param serialCode  SerialNumInfo唯一辨別code
     * @return
     */
    @PostMapping(value = "/getCurrentNum")
    @ApiOperation(value = "擷取目前編号")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(value = "關聯對象字元串", name = "relationObj"),
            @ApiImplicitParam(value = "編号資訊編碼", name = "serialCode")
    })
    @ResponseBody
    public ResponseMessage getCurrentNum(@RequestParam(required = true) String relationObj, @RequestParam(required = true) String serialCode) {

        return serialNumService.getCurrentNum(relationObj, serialCode);
    }

    /**
     * 擷取下一個編号
     *
     * @param relationObj 關聯對象
     * @param serialCode  SerialNumInfo唯一辨別code
     * @return
     */
    @PostMapping(value = "/getNextNum")
    @ApiOperation(value = "擷取下一個編号")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(value = "關聯對象字元串", name = "relationObj"),
            @ApiImplicitParam(value = "編号資訊編碼", name = "serialCode")
    })
    @ResponseBody
    public ResponseMessage getNextNum(@RequestParam(required = true) String relationObj, @RequestParam(required = true) String serialCode) {
        return serialNumService.getNextNum(relationObj, serialCode);
    }

    /**
     * 編号回退
     *
     * @param relationObj 編号回退
     * @param serialCode  SerialNumInfo唯一辨別code
     * @param step        回退步長
     */
    @PostMapping(value = "/fallbackNum")
    @ApiOperation(value = "編号回退")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(value = "關聯對象字元串", name = "relationObj"),
            @ApiImplicitParam(value = "編号資訊編碼", name = "serialCode"),
            @ApiImplicitParam(value = "回退步長", name = "step")
    })
    @ResponseBody
    public ResponseMessage<SerialNumRelationDTO> fallbackNum(@RequestParam(required = true) String relationObj, @RequestParam(required = true) String serialCode, @RequestParam(required = true) int step) {
        return serialNumService.fallbackNum(relationObj, serialCode, step);
    }

    /**
     * 歸零
     */
    @PostMapping(value = "/returnToZero")
    @ApiOperation(value = "歸零")
    @ApiImplicitParams(value = {
            @ApiImplicitParam(value = "歸零", name = "serialNumRelation")
    })
    @ResponseBody
    public ResponseMessage retToZero(@RequestBody(required = true) SerialNumRelationDTO serialNumRelationDTO) {
        return serialNumService.retToZero(serialNumRelationDTO);
    }
}
           
service層,帶有業務邏輯的service
public interface SerialNumServiceI    {
	/**
	 * 編号資訊新增/修改
	 * @param serialNumInfoDTO
	 * @return
	 */
	ResponseMessage doSave(SerialNumInfoDTO serialNumInfoDTO);
	/**
	 * 根據主鍵id擷取編号資訊詳情
	 * @param id
	 * @return
	 */
	ResponseMessage<SerialNumInfoDTO> getDetail(String id);
	/**
	 * 編号資訊清單
	 * @return
	 */
	ResponseMessage<List<SerialNumInfoDTO>> getList(SerialNumInfoDTO serialNumInfoDTO);
	/**
	 * 編号資訊狀态變更
	 * @param id
	 * @param status
	 */
	void changeStatus(String id, int status);
	/**
	 * 編号資訊删除
	 * @param id
	 */
	void doDelete(String id);
	/**
	 * 建立編号對象關聯
	 * @param serialNumRelationDTO
	 * @return
	 */
	ResponseMessage<SerialNumRelationDTO> createRelation(SerialNumRelationDTO serialNumRelationDTO);
	/**
	 * 編号對象關聯清單
	 * @param serialId
	 * @return
	 */
	ResponseMessage<List<SerialNumRelationDTO>> getRelationList(String serialId);
	/**
	 * 擷取編号對象關聯詳情
	 * @param id SerialNumRelation主鍵id
	 * @return
	 */
	ResponseMessage<SerialNumRelationDTO> getRelationDetail(String id);
	/**
	 * 擷取目前編号
	 * @param relationObj 關聯對象
	 * @param serialCode SerialNumInfo唯一辨別code
	 * @return
	 */
	ResponseMessage<SerialNumRelationDTO> getCurrentNum(String relationObj, String serialCode);
	/**
	 *  擷取下一個編号
	 * @param relationObj 關聯對象
	 * @param serialCode SerialNumInfo唯一辨別code
	 * @return
	 */
	ResponseMessage<SerialNumRelationDTO> getNextNum(String relationObj, String serialCode);
	/**
	 * 編号回退
	 * @param relationObj 關聯對象
	 * @param serialCode SerialNumInfo唯一辨別code
	 * @param step 回退步長
	 */
	ResponseMessage<SerialNumRelationDTO> fallbackNum(String relationObj, String serialCode, int step);
	/**
	 * 歸零
	 * @param zeroCycle
	 * @return
	 */
	ResponseMessage<SerialNumRelationDTO> retToZero(SerialNumRelationDTO serialNumRelationDTO);
}
           
service的實作類—最重要的一個
package org.hrvc.modules.serialnum.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.hrvc.common.api.vo.ResponseMessage;
import org.hrvc.common.api.vo.Result;
import org.hrvc.common.constant.CommonConstant;
import org.hrvc.common.util.DateUtils;
import org.hrvc.common.util.HRVCConverter;
import org.hrvc.common.util.StringUtils;
import org.hrvc.modules.serialnum.dto.SerialNumInfoDTO;
import org.hrvc.modules.serialnum.dto.SerialNumRelationDTO;
import org.hrvc.modules.serialnum.entity.SequenceModel;
import org.hrvc.modules.serialnum.entity.SerialNumInfoModel;
import org.hrvc.modules.serialnum.entity.SerialNumRelationModel;
import org.hrvc.modules.serialnum.mapper.SerivalNumMapper;
import org.hrvc.modules.serialnum.service.SequenceService;
import org.hrvc.modules.serialnum.service.SerialNumInfoService;
import org.hrvc.modules.serialnum.service.SerialNumRelationService;
import org.hrvc.modules.serialnum.service.SerialNumServiceI;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import javax.management.relation.RelationService;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 編号實作類
 * @Author: dongxaiomeng
 * @since: 2020/11/16
 * @Version: V1.0
 */

@Service
@Slf4j
public class SerialNumServiceImpl implements SerialNumServiceI {

    @Autowired
    private SerivalNumMapper serivalNumMapper;
    @Autowired
    private SerialNumRelationService relationService;
    @Autowired
    private SerialNumInfoService infoService;
    @Autowired
    private SequenceService sequenceService;

    /**
     * 編号資訊新增/修改
     *
     * @param serialNumInfoDTO
     * @return
     */
    @Override
    public ResponseMessage doSave(SerialNumInfoDTO serialNumInfoDTO) {
        //建立一個infomodel對象,用來向資料庫存入資料
        SerialNumInfoModel serialNumInfoModel = new SerialNumInfoModel();
        //調用corvet方法,轉存資料
        corvet(serialNumInfoDTO, serialNumInfoModel);//調用corvet方法,轉存資料
        BeanUtils.copyProperties(serialNumInfoDTO, serialNumInfoModel);
        //判斷info表中Id是否已經存在
        if (StringUtils.isEmpty(serialNumInfoModel.getId())) {
            //資料庫編号加了索引,判斷編号是否重複
            try {
                //id不存在,新增編号資訊
                infoService.save(serialNumInfoModel);
                return ResponseMessage.ok("新增成功");
            } catch (DuplicateKeyException exception) {
                return ResponseMessage.error("編号已存在,請重新輸入");
            }
        }
        //id 已存在時,修改編号資訊
        else {
            infoService.updateById(serialNumInfoModel);
            return ResponseMessage.ok("修改成功");
        }
    }

    //此方法用來轉存資料,在編号新增接口中有調用
    private void corvet(SerialNumInfoDTO serialNumInfoDTO, SerialNumInfoModel serialNumInfoModel) {
        serialNumInfoModel.setCode(serialNumInfoDTO.getCode());
        serialNumInfoModel.setName(serialNumInfoDTO.getName());
        serialNumInfoModel.setPreString(serialNumInfoDTO.getPreString());
        serialNumInfoModel.setLastString(serialNumInfoDTO.getLastString());
        serialNumInfoModel.setTimeFormat(serialNumInfoDTO.getTimeFormat());
        serialNumInfoModel.setTimeLocation(serialNumInfoDTO.getTimeLocation());
    }

    /**
     * 編号資訊删除
     *
     * @param id
     */
    @Override
    public void doDelete(String id) {
        //編号删除為邏輯删除,隻是更改了del_flag字段的值,0代表未删除,1代表已删除,需要注意的是邏輯删除會影響查詢方法,在查詢編号資訊的時候,需要把del_flag==1的編号資訊過濾掉
        //這裡用的是lambda表達式來做字段更改,在資料庫中,給del_flag字段加了索引.
        infoService.update(new UpdateWrapper<SerialNumInfoModel>().lambda()
                .eq(SerialNumInfoModel::getId, id)
                .set(SerialNumInfoModel::getDeleteFlag, CommonConstant.DEL_FLAG_1));
    }

    /**
     * 根據主鍵id擷取編号資訊詳情
     *
     * @param id
     * @return
     */
    @Override
    public ResponseMessage getDetail(String id) {
        //擷取info表中的id,這裡是精确查詢
        SerialNumInfoModel serialNumInfoModel = infoService.getById(id);
        //建立一個DTO對象,用來傳參
        SerialNumInfoDTO serialNumInfoDTO = new SerialNumInfoDTO();
        //把從資料庫取出的值,傳回DTO層,此處借用了傑哥的方法
        BeanCopier copier = BeanCopier.create(SerialNumInfoModel.class, SerialNumInfoDTO.class, true);
        copier.copy(serialNumInfoModel, serialNumInfoDTO, new HRVCConverter());
        //傳回值
        return ResponseMessage.ok(serialNumInfoDTO);
    }

    /**
     * 編号資訊清單
     */
    @Override
    public ResponseMessage<List<SerialNumInfoDTO>> getList(SerialNumInfoDTO serialNumInfoDTO) {
        //建立傳回值對象
        ResponseMessage<List<SerialNumInfoDTO>> result = new ResponseMessage<List<SerialNumInfoDTO>>();
        //查詢清單,條件用lambda篩選,like 模糊查詢
        List<SerialNumInfoModel> modelList = infoService.list(new QueryWrapper<SerialNumInfoModel>()
                .lambda()
                //通過傳進來的code查詢
                .like(SerialNumInfoModel::getCode, serialNumInfoDTO.getCode())
                .or()
                //通過傳進來的name查詢
                .like(SerialNumInfoModel::getName, serialNumInfoDTO.getName())
        );
        //過濾deleteflag=1的編号資訊
		/*List<SerialNumInfoModel> resultList = modelList.stream()
				.filter(serialNumInfoModel -> (serialNumInfoModel.getDeleteFlag()==1))
				.collect(Collectors.toList());*/
        //定義serialNumInfo,
        SerialNumInfoDTO serialNumInfo = null;
        //建立清單對象
        List<SerialNumInfoDTO> serialNumInfoList = new ArrayList<SerialNumInfoDTO>();
        //for循環用來幹嘛的呢,就是取出清單,把資料庫的每條資訊賦給DTO取出來.
        for (SerialNumInfoModel model : modelList) {
            //用來接收資料庫的資訊的DTO層
            serialNumInfo = new SerialNumInfoDTO();
            //從資料庫model指派給dto
            BeanCopier copier = BeanCopier.create(SerialNumInfoModel.class, SerialNumInfoDTO.class, true);
            copier.copy(model, serialNumInfo, new HRVCConverter());
            serialNumInfoList.add(serialNumInfo);
        }
        //傳回結果指派
        result.setResult(serialNumInfoList);
        return result;
    }

    /**
     * 編号資訊狀态變更
     *
     * @param id
     * @param status
     */
    @Override
    //這個方法就是改變編号資訊的狀态,和它相關即要操作的字段就是info表的Status,0-抑制,1-啟用,2-禁用
    public void changeStatus(String id, int status) {
        //根據id更新status的内容
        infoService.update(new UpdateWrapper<SerialNumInfoModel>().lambda()
                .eq(SerialNumInfoModel::getId, id)
                .set(SerialNumInfoModel::getStatus, status));
    }

    /**
     * 建立/修改編号對象關聯
     *
     * @param serialNumRelationDTO
     * @return
     */
    @Override
    public ResponseMessage createRelation(SerialNumRelationDTO serialNumRelationDTO) {
        //建立一個relationModel 對象,用來接DTO傳過來的資料
        SerialNumRelationModel serialNumRelationModel = new SerialNumRelationModel();
        //建立sequence對象,往sequence表中加資料
        SequenceModel sequenceModel = new SequenceModel();
        //将dto的資料存到entity中
        BeanUtils.copyProperties(serialNumRelationDTO, serialNumRelationModel);
        serialNumRelationModel.setSerialId(serialNumRelationDTO.getSerialNumInfo().getId());
        //往sequence中加資料
        sequenceModel.setName(serialNumRelationDTO.getSequenceName());
        sequenceModel.setCurrentValue(serialNumRelationDTO.getStartNum());
        //在這裡是把id是否唯一作為判斷條件,
        if (StringUtils.isEmpty(serialNumRelationModel.getId())) {
            try {
                //id不存在,新增編号關聯資訊和初始序号
                relationService.save(serialNumRelationModel);
                sequenceService.save(sequenceModel);
                return ResponseMessage.ok("新增成功");
            } catch (DuplicateKeyException exception) {
                return ResponseMessage.error("編号關聯已存在,請重新輸入");
            }
        }
        //id 已存在時,修改編号關聯資訊
        else {
            relationService.updateById(serialNumRelationModel);
            return ResponseMessage.ok("修改成功");
        }
    }
    /**
     * 編号對象關聯清單
     *
     * @return
     */
    @Override
    public ResponseMessage<List<SerialNumRelationDTO>> getRelationList(String serialId) {
        //傳回值
        ResponseMessage<List<SerialNumRelationDTO>> result = new ResponseMessage<List<SerialNumRelationDTO>>();
        //根據seralId得到relationModel
        List<SerialNumRelationModel> modelList = relationService.list(new QueryWrapper<SerialNumRelationModel>()
                .lambda()
                .eq(SerialNumRelationModel::getSerialId, serialId));
        //初始化DTO,傳回值時要用
        SerialNumRelationDTO serialNumRelationDTO = null;
        //建立relationDTOList集合,用來存從資料庫取出的資料
        List<SerialNumRelationDTO> serialNumRelationDTOList = new ArrayList<SerialNumRelationDTO>();
        //這個循環用來從資料庫中取資料,存到dto中,但是未實作.
        //SerialNumInfoModel serialNumInfoModel = new SerialNumInfoModel();
        for (SerialNumRelationModel model : modelList) {
            //建立一個relationDTO對象,用來轉存資料
            serialNumRelationDTO = new SerialNumRelationDTO();
            //從資料庫取值指派
            BeanCopier copier = BeanCopier.create(SerialNumRelationModel.class, SerialNumRelationDTO.class, true);
            copier.copy(model, serialNumRelationDTO, new HRVCConverter());
            serialNumRelationDTOList.add(serialNumRelationDTO);
        }
        //傳回存儲
        result.setResult(serialNumRelationDTOList);
        return result;
    }

    /**
     * 擷取編号對象關聯詳情
     *
     * @param id SerialNumRelation主鍵id
     * @return
     */
    @Override
    public ResponseMessage getRelationDetail(String id) {
        //取出relation的id,精确查詢
        SerialNumRelationModel serialNumRelationModel = relationService.getById(id);
        //建立一個DTO,用來将資料庫取出的值傳出來
        SerialNumRelationDTO serialNumRelationDTO = new SerialNumRelationDTO();
        //資料轉換
        BeanCopier copier = BeanCopier.create(SerialNumRelationModel.class, SerialNumRelationDTO.class, true);
        copier.copy(serialNumRelationModel, serialNumRelationDTO, new HRVCConverter());
        return ResponseMessage.ok(serialNumRelationDTO);
    }

    /**
     * 根據relation,serialCode,從資料庫取出sequenceName
     *
     * @param relationObj
     * @param serialCode
     * @return
     */
    private Map<String, Object> getSerialInfo(String relationObj, String serialCode) {
        //1.根據serialCode查詢serialNumInfoModel
        SerialNumInfoModel serialNumInfoModel = infoService.getOne(new QueryWrapper<SerialNumInfoModel>()
                .lambda()
                //擷取資料庫中相等的code的資料
                .eq(SerialNumInfoModel::getCode, serialCode));
        //2. 根據relationObj和serialNumInfoModel.id 查詢SerialNumRelationModel
        SerialNumRelationModel serialNumRelationModel = relationService.getOne(new QueryWrapper<SerialNumRelationModel>()
                .lambda()
                //通過上面的code找到info的id和relation中serival_id相等的關聯表的relationobj,
                .eq(SerialNumRelationModel::getSerialId, serialNumInfoModel.getId())
                .eq(SerialNumRelationModel::getRelationObj, relationObj));
        //定義傳回的result
        Map<String, Object> result = new HashMap<String, Object>();
        //把infomodel和relationmodel中的資料存儲.
        result.put("serialNumInfoModel", serialNumInfoModel);
        result.put("serialNumRelationModel", serialNumRelationModel);
        return result;
    }

    /**
     * 根據傳遞的sequenceNum和serialNumInfoModel以及serialNumRelationModel 拼接編号字元串
     *
     * @param serialNumInfoModel
     * @param serialNumRelationModel
     * @param sequenceNum
     * @return
     */
    private String formatCodeNum(SerialNumInfoModel serialNumInfoModel, SerialNumRelationModel serialNumRelationModel, int sequenceNum) {
        //字元串類型,下面可用于資料類型轉換成字元串
        String codeNumStr = "";
        // ${seq}前面的部分
        //擷取自增序列的最大長度
        serialNumRelationModel.getSeqMaxlength();
        //擷取是否補零
        serialNumRelationModel.getPadding();
	   /* if(sequenceNum % serialNumRelationModel.getSeqMaxlength()*10) {
		throw new Exception("超過最大長度,請檢查配置");
	    }*/
        //擷取資料庫中的序列前置字元
        String seqNumCode = serialNumRelationModel.getSeqPre();//
        // 判斷是否需要進行補0
        if (1 == serialNumRelationModel.getPadding()) {
            //zeroLen是資料庫定義的序列最大長度-前端傳過來的sequenceNum的長度值   String.valueOf(sequenceNum).length()
            int zeroLen = serialNumRelationModel.getSeqMaxlength() - String.valueOf(sequenceNum).length();
            //将sequenceNum轉化為字元串
            String seqNumStr = String.valueOf(sequenceNum);
            //for循環,用來補零操作,條件為當
            for (int i = 0; i < zeroLen; i++) {
                seqNumStr = 0 + seqNumStr;
            }
            seqNumCode += seqNumStr;
        } else {
            seqNumCode += sequenceNum;
        }
        // ${seq}前面的部分
        //時間位置
        String str0 = "";//左
        String str1 = "";//中
        String str2 = "";//右
        // 沒有時間輸出
        if (!"無".equals(serialNumInfoModel.getTimeLocation()) && !"無".equals(serialNumInfoModel.getTimeFormat())) {
            // 有時間輸出,則需要根據位置進行拼接
            String dateTimeStr = DateUtils.getDate(serialNumInfoModel.getTimeFormat());
            switch (serialNumInfoModel.getTimeLocation()) {
                case 1:
                    str0 = dateTimeStr;
                    break;
                case 2:
                    str1 = dateTimeStr;
                    break;
                case 3:
                    str2 = dateTimeStr;
                    break;
            }
        }
        //根據時間位置進行編号組合
        codeNumStr = str0 + serialNumInfoModel.getPreString() + str1 + serialNumInfoModel.getLastString() + str2;
        codeNumStr = codeNumStr + seqNumCode;
        return codeNumStr;
    }

    /**
     * 擷取目前編号
     *
     * @param relationObj 關聯對象
     * @param serialCode  SerialNumInfo唯一辨別code
     * @return
     */
    @Override
    public ResponseMessage getCurrentNum(String relationObj, String serialCode) {

        //這是調用根據relationObj和serialCode擷取資料庫的值
        Map<String, Object> map = getSerialInfo(relationObj, serialCode);
        //根據第2步驟SerialNumRelationModel.sequenceName 執行函數currval(map.get("serialNumRelationModel").getSequence())
        //擷取函數得到的目前序列
        int num = getCurrval(((SerialNumRelationModel) map.get("serialNumRelationModel")).getSequenceName());
        //強轉擷取infomodel
        SerialNumInfoModel serialNumInfoModel = (SerialNumInfoModel) map.get("serialNumInfoModel");
        //強轉擷取relationmodel
        SerialNumRelationModel serialNumRelationModel = (SerialNumRelationModel) map.get("serialNumRelationModel");
        if (serialNumRelationModel.getSeqMaxlength() >= String.valueOf(num).length()) {
            String code = formatCodeNum(serialNumInfoModel, serialNumRelationModel, num);
            //傳回code
            return ResponseMessage.ok(code);
        } else {
            //當序号大于最大數時,取最大數,

            return ResponseMessage.error("目前序号不合規範,大于序号最大值");
        }
        //調用拼接編号的方法
        //String code = formatCodeNum(serialNumInfoModel, serialNumRelationModel, num);
        //傳回code
        //  return ResponseMessage.ok(code);
    }

    //這是目前序列的函數調用方法,和mapper.xml層連接配接的方法
    private int getCurrval(String seqName) {
        int currentNum = serivalNumMapper.getCurrvalNum(seqName);
        return currentNum;
    }

    /**
     * 擷取下一個編号
     *
     * @param relationObj 關聯對象
     * @param serialCode  SerialNumInfo唯一辨別code
     * @return
     */
    @Override
    public ResponseMessage getNextNum(String relationObj, String serialCode) {
        //從資料取值
        Map<String, Object> map = getSerialInfo(relationObj, serialCode);
        //3.根據第2步驟SerialNumRelationModel.sequenceName 執行函數nextval(map.get("serialNumRelationModel").getSequence())
        //函數取序号
        // int num = getNextNum(((SerialNumRelationModel) map.get("serialNumRelationModel")).getSequenceName());
        int num = getNextNum(((SerialNumRelationModel) map.get("serialNumRelationModel")).getSequenceName());
        //取infoModel
        SerialNumInfoModel serialNumInfoModel = (SerialNumInfoModel) map.get("serialNumInfoModel");
        //取relationModel
        SerialNumRelationModel serialNumRelationModel = (SerialNumRelationModel) map.get("serialNumRelationModel");
        //判斷num是否符合規範,即長度是否大于序列長度
        if (serialNumRelationModel.getSeqMaxlength() >= String.valueOf(num).length()) {
            String code = formatCodeNum(serialNumInfoModel, serialNumRelationModel, num);
            //傳回code
            return ResponseMessage.ok(code);
        } else {
            return ResponseMessage.error("下一個自增序号大于序号最大長度,不可再取.請擴大自增序号長度");
        }
    }

    //下一個編号的函數調用方法,和mapper.xml層聯系
    private int getNextNum(String seqName) {
        int nextNum = serivalNumMapper.getNextNum(seqName);
        return nextNum;
    }

    /**
     * 編号回退
     *
     * @param relationObj 關聯對象
     * @param serialCode  SerialNumInfo唯一辨別code
     * @param step        回退步長
     */
    @Override
    public ResponseMessage fallbackNum(String relationObj, String serialCode, int step) {
        Map<String, Object> map = getSerialInfo(relationObj, serialCode);
        //3.根據第2步驟SerialNumRelationModel.sequenceName 執行函數nextval(map.get("serialNumRelationModel").getSequence())
        SerialNumRelationModel relationModel = (SerialNumRelationModel) map.get("serialNumRelationModel");
        // 擷取目前sequence值
        int currentNum = serivalNumMapper.getCurrvalNum(relationModel.getSequenceName());
        // 判斷回退是否小于起始值
        if (relationModel.getStartNum() > (currentNum - step)) {
            return ResponseMessage.error("回退失敗,回退後小于起始值" + relationModel.getStartNum() + ",請檢查确認");
        } else {
            //函數取序号
            int num = getFallbackNum(((SerialNumRelationModel) map.get("serialNumRelationModel")).getSequenceName(), currentNum - step);
            if (num > 0) {
                return ResponseMessage.ok("回退成功");
            }
            return ResponseMessage.error("回退失敗,回退後小于起始值" + relationModel.getStartNum() + ",請檢查确認");
        }
    }

    //編号回退的函數調用方法,和mapper.xml層聯系
    private int getFallbackNum(String seqName, Integer setVal) {
        int fallbackNum = serivalNumMapper.getFallbackNum(seqName, setVal);
        return fallbackNum;
    }

    /**
     * 歸零
     *
     * @return
     */
    @Override
    public ResponseMessage retToZero(SerialNumRelationDTO serialNumRelationDTO) {
        //初始化
        List<SerialNumRelationModel> modelList = null;
        //擷取歸零周期
        try {
            modelList = relationService.list(new QueryWrapper<SerialNumRelationModel>()
                    .lambda()
                    .eq(SerialNumRelationModel::getZeroCycle, serialNumRelationDTO.getZeroCycle()));
        } catch (Exception e) {
            return ResponseMessage.error("歸零失敗");
        }
        //更新序号
        try {
            for (SerialNumRelationModel relationModel : modelList) {
                sequenceService.update(new UpdateWrapper<SequenceModel>()
                        .lambda()
                        .eq(SequenceModel::getName, relationModel.getSequenceName())
                        .set(SequenceModel::getCurrentValue, relationModel.getStartNum()));
                return ResponseMessage.ok("歸零成功");
            }
        } catch (Exception e) {
            return ResponseMessage.error("歸零失敗");
        }
        return ResponseMessage.error("歸零失敗");
    }
}
           

這裡有三個接口用到了資料庫函數來寫的,就是sequence表,相關接口就是目前序列号和下一個序列号,還有復原序号三個接口,這三個要好好學習.