某自动化制造业生产,需要在A-5工位上打标并生成真实的生产条形码,生成的真实条形码需要覆盖之前的A-1,A-2,A-3,A-4的虚拟条形码。并且B工站组,C攻占组,.....N工站组都有相同的需求。而且需要覆盖的工站不固定。
设计思路
插入的json格式
package com.smartflow.dto; import com.fasterxml.jackson.annotation.JsonProperty; /** * @author haita */ public class AddCLStationDeviceDTO { private String LinkTableName; private Object Object; @Override public String toString() { return "AddCLStationDeviceDTO{" + "LinkTableName='" + LinkTableName + '\'' + ", Object=" + Object + '}'; } @JsonProperty("LinkTableName") public String getLinkTableName() { return LinkTableName; } public void setLinkTableName(String linkTableName) { LinkTableName = linkTableName; } @JsonProperty("Object") public java.lang.Object getObject() { return Object; } public void setObject(java.lang.Object object) { Object = object; } }
object是通用的数据,因为有100多个工站,所以会有100多个表。
利用这样的数据格式可以很好的利用java的反射原理。(可以在我以前的文章中找到)进行通用接口的数据插入。
接着根据表名判断是否需要,重写之前的表中的虚拟条形码。
package com.smartflow.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.smartflow.common.stationenum.StationEnumUtil; import com.smartflow.dto.AddCLStationDeviceDTO; import com.smartflow.service.CL_StationService; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * @author haita */ @RestController @RequestMapping("/api/CLStation") public class ClStationController extends BaseController{ private static Logger logger = Logger.getLogger(ClStationController.class); private final CL_StationService clStationService; private static final int ERROR_CODE=0; private static final int SUCEESS_CODE=200; private static final String SERIAL_ARG="SERIALNUMBER"; @Autowired public ClStationController(CL_StationService clStationService ) { this.clStationService = clStationService; } /** * 添加工站设备生产信息 * @return 返回前端是否添加成功信息 */ @CrossOrigin(origins="*",maxAge=3600) @PostMapping(value="/AddCLStationDevice") public Map<String, Object> addclstationdevice (@RequestBody AddCLStationDeviceDTO clStationDeviceDTO){ Map<String, Object> json = new HashMap<>(16); String linkTableName = clStationDeviceDTO.getLinkTableName(); String className = "com.smartflow.model."+linkTableName; if(StringUtils.isEmpty(linkTableName)){ json = this.setJson(ERROR_CODE, "添加失败:要添加的表名不能为空", -1); return json; } if(clStationDeviceDTO.getObject() == null){ json = this.setJson(ERROR_CODE, "添加失败:要添加对象不能为空", -1); return json; } try { JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(clStationDeviceDTO.getObject())); Integer workOrderId = clStationService.getCurrentActivedWorkOrder(); jsonObject.put("WorkOrderId",workOrderId); String serialNumber = jsonObject.get(SERIAL_ARG) == null ? null : jsonObject.get(SERIAL_ARG).toString(); clStationDeviceDTO.setObject(reWrite(serialNumber,jsonObject,linkTableName)); clStationService.addCLStationDevice(className, parseToEntity(linkTableName, clStationDeviceDTO)); json = this.setJson(SUCEESS_CODE, "添加成功!", 1); } catch (Exception e) { logger.info(e.getCause()); e.printStackTrace(); } return json; } /** * 利用反射根据表名生成实体 * @param linkedName 表名 * @param clStationDeviceDTO 请求参数 * @return 返回请求实体 * @throws ClassNotFoundException 根据表名未查到相应的类 */ @SuppressWarnings("unckecked") private Object parseToEntity(String linkedName,AddCLStationDeviceDTO clStationDeviceDTO) throws ClassNotFoundException { Class<?> classEntity=Class.forName("com.smartflow.model."+linkedName); return JSON.parseObject (JSON.toJSONString(clStationDeviceDTO.getObject()), classEntity); } /** * 根据seialNumber和linkTableName判断是否覆盖op50以前的serialNumber * @param serialNumber 条形码 * @param jsonObject 请求实体 * @param linkTableName 请求表名 * @return 返回修饰的请求实体 */ private JSONObject reWrite(String serialNumber,JSONObject jsonObject,String linkTableName) { /* * 判断是否是需要覆盖的表,覆盖的表有state,且初始的时候置0 * 包含工站组Tu,Re,Im */ if (StationEnumUtil.isReWriteStation(linkTableName)) { jsonObject.put("state", 0); } /* * 请求实体中未包含二维条码,会按日期格式生成二维序列码 */ jsonObject.put("SerialNumber", new Date().toString()); /* * 判断是否是最后一个工站Tuop50,Imop15,Reop45,是的话覆盖前面的工站 */ if (StationEnumUtil.isLastStation(linkTableName)) { Date date = new Date(); if (serialNumber == null||"".equals(serialNumber) ) { jsonObject.put(SERIAL_ARG, date.toString()); clStationService.reWriteSerialNumber(date.toString(),linkTableName); } else { jsonObject.put(SERIAL_ARG, serialNumber); clStationService.reWriteSerialNumber(serialNumber,linkTableName); } } return jsonObject; } }
覆盖算法
private void setSerialNumber(String serialNumber,String tableName) throws ClassNotFoundException { try { List<?> stationList = hibernateTemplate.find ("from "+tableName + " where state=0 order by CREATE_DATE "); if (!stationList.isEmpty()) { Object station = stationList.get(0); String jsonString=JSONObject.toJSONString(station); JSONObject jsonObject=JSONObject.parseObject(jsonString); jsonObject.put("SerialNumber",serialNumber); jsonObject.put("State",1); Class<?> classEntity=Class.forName ("com.smartflow.model."+tableName); hibernateTemplate.clear(); hibernateTemplate.update (JSON.parseObject(jsonObject.toString(), classEntity)); } }catch (Exception e) { e.printStackTrace(); throw e; } }
可以看到我利用先进先出的规范,根据时间找到最晚未被覆盖的那条数据,也是就是state为0,利用state是否为0来表示是否是被覆盖过的。
更加通用的写法,可以把各个攻占组将要覆盖的工站表,建立一个枚举。
package com.smartflow.common.stationenum; /** * @author :tao * @date :Created in 2020/8/14 14:48 */ public enum StationNameRe { /** * RE工站需要覆盖的工站 */ RE_OP10A("RE_OP10A"),RE_OP10B("RE_OP10B"); private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } StationNameRe(String name) { this.name=name; } }
package com.smartflow.common.stationenum; /** * @author :tao * @date :Created in 2020/8/10 15:51 */ public enum StationNameTu { /** * TUOP描述 */ CL_TUOP20("CL_TUOP20"),CL_TU0P25("CL_TU0P25"),CL_TUOP30("CL_TUOP30"), CL_TUOP45("CL_TUOP45"),CL_WLZPDM("CL_WLZPDM"); public String getName() { return name; } public void setName(String name) { this.name = name; } private String name; StationNameTu(String name) { this.name=name; } }
package com.smartflow.common.stationenum; /** * @author :tao * @date :Created in 2020/8/14 14:50 */ public enum StationNameIm { /** * IM工站需要覆盖的工站位 */ IM_OP20("IM_OP20"),IM_OP25("IM_OP25"),IM_OP30("IM_OP30"),IM_OP40("IM_OP40"); public String getName() { return name; } public void setName(String name) { this.name = name; } private String name; StationNameIm(String name){ this.name=name; } }
然后可以根据不同的枚举类去做不同的覆盖队列
@Transactional(rollbackFor = Exception.class) @Override public void reWriteSerialNumber(String serialNumber,String tableName) { try { if (StationEnumUtil.isRe(tableName)) { for (StationNameRe stationNameRe : StationNameRe.values()) { setSerialNumber(serialNumber, stationNameRe.getName()); } } if (StationEnumUtil.isTu(tableName)) { for (StationNameTu stationNameTu:StationNameTu.values()) { setSerialNumber(serialNumber, stationNameTu.getName()); } } if (StationEnumUtil.isIm(tableName)) { for (StationNameIm stationNameIm:StationNameIm.values()) { setSerialNumber(serialNumber, stationNameIm.getName()); } } } catch (Exception e) { e.printStackTrace(); } }
当然以上还是最基本的在最理想的状态下的做法。未来要进行生产的话还需要大量的NG处理,事物的回滚,防错等等。