feat(ems): 添加ASSIGN_ID主键策略与批量告警处理

- 为多个领域模型添加 @TableId(type = IdType.ASSIGN_ID) 注解以统一雪花算法主键生成,
- 重构告警确认逻辑支持批量查询与更新以提升性能,并清理冗余的 getter 方法。
main
zch 1 month ago
parent 7c3b0a1411
commit 148585722b

@ -104,4 +104,5 @@ public class EmsBaseMonitorInfoController extends EmsBaseController
{
return toAjax(emsBaseMonitorInfoService.deleteEmsBaseMonitorInfoByObjIds(objIds));
}
}

@ -1,6 +1,8 @@
package org.dromara.ems.base.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -24,6 +26,7 @@ public class EmsAlarmActionStep extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键ID */
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private String objId;
/** 关联的报警规则ID (逻辑关联 ems_record_alarm_rule.obj_id) */

@ -1,6 +1,8 @@
package org.dromara.ems.base.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -24,6 +26,7 @@ public class EmsAlarmActionStepImage extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键ID */
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private String objId;
/** 关联的措施步骤ID */

@ -1,8 +1,11 @@
package org.dromara.ems.base.domain;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.dromara.common.mybatis.core.domain.BaseEntity;
@ -16,6 +19,7 @@ import java.util.Date;
* @author Yinq
* @date 2024-05-20
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class EmsBaseCollectDeviceInfo extends BaseEntity {
@Serial
@ -24,6 +28,7 @@ public class EmsBaseCollectDeviceInfo extends BaseEntity {
/**
*
*/
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/**
@ -142,10 +147,6 @@ public class EmsBaseCollectDeviceInfo extends BaseEntity {
private String onlineStatus;
public String getEnergyTypeName() {
return energyTypeName;
}
public void setEnergyTypeName(String energyTypeName) {
this.energyTypeName = energyTypeName;
}
@ -154,238 +155,118 @@ public class EmsBaseCollectDeviceInfo extends BaseEntity {
this.objId = objId;
}
public Long getObjId() {
return objId;
}
public void setCollectDeviceId(String collectDeviceId) {
this.collectDeviceId = collectDeviceId;
}
public String getCollectDeviceId() {
return collectDeviceId;
}
public void setCollectDeviceName(String collectDeviceName) {
this.collectDeviceName = collectDeviceName;
}
public String getCollectDeviceName() {
return collectDeviceName;
}
public void setEnergyTypeId(Long energyTypeId) {
this.energyTypeId = energyTypeId;
}
public Long getEnergyTypeId() {
return energyTypeId;
}
public void setModel(String model) {
this.model = model;
}
public String getModel() {
return model;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getManufacturer() {
return manufacturer;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public String getIpAddress() {
return ipAddress;
}
public void setProduceDate(Date produceDate) {
this.produceDate = produceDate;
}
public Date getProduceDate() {
return produceDate;
}
public void setSettingAddress(String settingAddress) {
this.settingAddress = settingAddress;
}
public String getSettingAddress() {
return settingAddress;
}
public void setIsFlag(String isFlag) {
this.isFlag = isFlag;
}
public String getIsFlag() {
return isFlag;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getTenantId() {
return tenantId;
}
public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}
public String getProtocolType() {
return protocolType;
}
public void setProtocolType(String protocolType) {
this.protocolType = protocolType;
}
public String getProtocolVersion() {
return protocolVersion;
}
public void setProtocolVersion(String protocolVersion) {
this.protocolVersion = protocolVersion;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public Integer getSlaveNo() {
return slaveNo;
}
public void setSlaveNo(Integer slaveNo) {
this.slaveNo = slaveNo;
}
public String getSerialPort() {
return serialPort;
}
public void setSerialPort(String serialPort) {
this.serialPort = serialPort;
}
public Integer getBaudRate() {
return baudRate;
}
public void setBaudRate(Integer baudRate) {
this.baudRate = baudRate;
}
public Integer getDataBits() {
return dataBits;
}
public void setDataBits(Integer dataBits) {
this.dataBits = dataBits;
}
public Integer getStopBits() {
return stopBits;
}
public void setStopBits(Integer stopBits) {
this.stopBits = stopBits;
}
public String getParity() {
return parity;
}
public void setParity(String parity) {
this.parity = parity;
}
public String getOpcEndpointUrl() {
return opcEndpointUrl;
}
public void setOpcEndpointUrl(String opcEndpointUrl) {
this.opcEndpointUrl = opcEndpointUrl;
}
public String getOpcSecurityPolicy() {
return opcSecurityPolicy;
}
public void setOpcSecurityPolicy(String opcSecurityPolicy) {
this.opcSecurityPolicy = opcSecurityPolicy;
}
public String getOpcSecurityMode() {
return opcSecurityMode;
}
public void setOpcSecurityMode(String opcSecurityMode) {
this.opcSecurityMode = opcSecurityMode;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Date getHeartbeatTime() {
return heartbeatTime;
}
public void setHeartbeatTime(Date heartbeatTime) {
this.heartbeatTime = heartbeatTime;
}
public Date getLastOnlineTime() {
return lastOnlineTime;
}
public void setLastOnlineTime(Date lastOnlineTime) {
this.lastOnlineTime = lastOnlineTime;
}
public Integer getOfflineTimeoutSec() {
return offlineTimeoutSec;
}
public void setOfflineTimeoutSec(Integer offlineTimeoutSec) {
this.offlineTimeoutSec = offlineTimeoutSec;
}
public String getOnlineStatus() {
return onlineStatus;
}
public void setOnlineStatus(String onlineStatus) {
this.onlineStatus = onlineStatus;
}

@ -2,6 +2,8 @@ package org.dromara.ems.base.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -28,6 +30,7 @@ public class EmsBaseEnergyPrice extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键标识 */
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/** 能源类型编号 */

@ -1,6 +1,8 @@
package org.dromara.ems.base.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -25,6 +27,7 @@ public class EmsBaseEnergyType extends BaseEntity
private static final long serialVersionUID = 1L;
/** 自增标识 */
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/** 能源类型编号 */

@ -1,6 +1,9 @@
package org.dromara.ems.base.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.dromara.common.mybatis.core.domain.BaseEntity;
@ -16,6 +19,7 @@ import java.util.List;
* @author Yinq
* @date 2024-05-08
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class EmsBaseMonitorInfo extends BaseEntity
{
@ -23,6 +27,7 @@ public class EmsBaseMonitorInfo extends BaseEntity
private static final long serialVersionUID = 1L;
/** 自增标识 */
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/** 计量设备编号 */

@ -1,6 +1,8 @@
package org.dromara.ems.base.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -26,6 +28,7 @@ public class EmsBaseMonitorThreshold extends BaseEntity {
/**
*
*/
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/**

@ -2,6 +2,8 @@ package org.dromara.ems.base.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -30,6 +32,7 @@ public class EmsBaseMonitorWorkUnit extends BaseEntity
/**
*
*/
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/**

@ -1,6 +1,8 @@
package org.dromara.ems.base.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -27,6 +29,7 @@ public class EmsBaseSharePrice extends BaseEntity
/**
*
*/
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/**

@ -2,6 +2,8 @@ package org.dromara.ems.base.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -28,6 +30,7 @@ public class EmsBaseWorkUnit extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键标识 */
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/** 统计单元编号 */

@ -1,6 +1,7 @@
package org.dromara.ems.base.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
@ -75,8 +76,13 @@ public class EmsBaseMonitorInfoServiceImpl implements IEmsBaseMonitorInfoService
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public int insertEmsBaseMonitorInfo(EmsBaseMonitorInfo emsBaseMonitorInfo)
{
if (emsBaseMonitorInfo.getObjId() == null) {
// 手写 XML 的动态列在 MyBatis-Plus 自动填充前已完成解析,这里提前生成 ASSIGN_ID 主键,避免 obj_id 未进入 INSERT 列。
emsBaseMonitorInfo.setObjId(IdWorker.getId());
}
emsBaseMonitorInfo.setCreateTime(DateUtils.getNowDate());
return emsBaseMonitorInfoMapper.insertEmsBaseMonitorInfo(emsBaseMonitorInfo);
}

@ -3,6 +3,8 @@ package org.dromara.ems.info.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -25,6 +27,7 @@ public class DailyFaultRecord extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键自增ID */
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/** 日期 */

@ -3,6 +3,8 @@ package org.dromara.ems.info.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -25,6 +27,7 @@ public class FaultHandlingRecord extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键自增ID */
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/** 故障日期 */

@ -3,6 +3,8 @@ package org.dromara.ems.info.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -25,6 +27,7 @@ public class LuggageSystemPlcBufferBatteryLifecycle extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键自增ID */
@TableId(value = "objid", type = IdType.ASSIGN_ID)
private Long objid;
/** 类型 */

@ -3,6 +3,8 @@ package org.dromara.ems.info.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -25,6 +27,7 @@ public class LuggageSystemSecurityDoorBatteryLifecycle extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键自增ID */
@TableId(value = "objid", type = IdType.ASSIGN_ID)
private Long objid;
/** 类型 */

@ -3,6 +3,8 @@ package org.dromara.ems.info.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -25,6 +27,7 @@ public class PowerEnergySparePartsRegistration extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键自增ID */
@TableId(value = "objid", type = IdType.ASSIGN_ID)
private Long objid;
/** 日期 */

@ -3,6 +3,8 @@ package org.dromara.ems.info.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -25,6 +27,7 @@ public class PowerEnergySupervisionChecklist extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键自增ID */
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/** 日期 */

@ -3,6 +3,8 @@ package org.dromara.ems.info.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -25,6 +27,7 @@ public class SparePartsInventory extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键 */
@TableId(value = "objid", type = IdType.ASSIGN_ID)
private Long objid;
/** 入库时间 */

@ -2,6 +2,8 @@ package org.dromara.ems.info.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -26,6 +28,7 @@ public class SparePartsInventoryCheck extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键 */
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/** 备件库存主表ID */

@ -3,6 +3,8 @@ package org.dromara.ems.info.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -25,6 +27,7 @@ public class SparePartsUsageRecord extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键自增ID */
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/** 日期 */

@ -3,6 +3,8 @@ package org.dromara.ems.info.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -25,6 +27,7 @@ public class UpsBatteryLifecycle extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键自增ID */
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/** 类型 */

@ -3,6 +3,8 @@ package org.dromara.ems.record.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -28,6 +30,7 @@ public class EmsRecordAlarmData extends BaseEntity
private static final long serialVersionUID = 1L;
/** 自增标识 */
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/** 计量设备编号 */

@ -3,6 +3,8 @@ package org.dromara.ems.record.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -28,6 +30,7 @@ public class EmsRecordAlarmRule extends BaseEntity
private static final long serialVersionUID = 1L;
/** 自增标识 */
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/** 规则编号 */

@ -3,6 +3,8 @@ package org.dromara.ems.record.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -28,6 +30,7 @@ public class EmsRecordDnbInstant extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键标识 */
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/** 计量设备编号 */

@ -3,6 +3,8 @@ package org.dromara.ems.record.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -31,6 +33,7 @@ public class EmsRecordSteamInstant extends BaseEntity
/**
*
*/
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/**

@ -3,6 +3,8 @@ package org.dromara.ems.record.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -28,6 +30,7 @@ public class EmsRecordWaterInstant extends BaseEntity
private static final long serialVersionUID = 1L;
/** */
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/** 计量设备编号 */

@ -3,6 +3,8 @@ package org.dromara.ems.record.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -40,6 +42,7 @@ public class EmsVibrationInstant extends BaseEntity
}
/** 主键标识 */
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/** 采集时间 */

@ -3,6 +3,8 @@ package org.dromara.ems.record.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -26,6 +28,7 @@ public class RecordIotenvInstant extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键标识 */
@TableId(value = "objid", type = IdType.ASSIGN_ID)
private Long objid;
/** 计量设备编号 */

@ -3,6 +3,8 @@ package org.dromara.ems.record.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -28,6 +30,7 @@ public class TWTempertureData extends BaseEntity
private static final long serialVersionUID = 1L;
/** 主键标识 */
@TableId(value = "objid", type = IdType.ASSIGN_ID)
private Long objid;
/** 计量设备编号 */

@ -4,6 +4,7 @@ import org.apache.ibatis.annotations.Param;
import org.dromara.ems.record.domain.EmsRecordAlarmData;
import org.dromara.ems.record.domain.vo.EmsRecordAlarmDataSummaryVo;
import java.util.Collection;
import java.util.Date;
import java.util.List;
@ -23,6 +24,17 @@ public interface EmsRecordAlarmDataMapper
*/
public EmsRecordAlarmData selectEmsRecordAlarmDataByObjId(Long objId);
/**
*
*
* <p> objId
* SELECT </p>
*
* @param objIds
* @return
*/
List<EmsRecordAlarmData> selectEmsRecordAlarmDataByObjIds(@Param("objIds") Collection<Long> objIds);
/**
*
*
@ -69,6 +81,19 @@ public interface EmsRecordAlarmDataMapper
*/
int markAlarmHandled(EmsRecordAlarmData emsRecordAlarmData);
/**
*
*
* <p> alarm_status
* </p>
*
* @param objIds
* @param emsRecordAlarmData
* @return
*/
int markAlarmHandledBatch(@Param("objIds") Collection<Long> objIds,
@Param("alarmData") EmsRecordAlarmData emsRecordAlarmData);
/**
*
*

@ -202,38 +202,73 @@ public class EmsRecordAlarmDataServiceImpl implements IEmsRecordAlarmDataService
return result;
}
result.setRequestCount(objIds.length);
Map<Long, Integer> requestCountMap = new LinkedHashMap<>();
for (Long objId : objIds) {
EmsRecordAlarmData existing = emsRecordAlarmDataMapper.selectEmsRecordAlarmDataByObjId(objId);
if (objId == null) {
throw new ServiceException("告警ID不能为空");
}
requestCountMap.merge(objId, 1, Integer::sum);
}
List<Long> uniqueObjIds = new ArrayList<>(requestCountMap.keySet());
List<EmsRecordAlarmData> existingAlarmList = emsRecordAlarmDataMapper.selectEmsRecordAlarmDataByObjIds(uniqueObjIds);
Map<Long, EmsRecordAlarmData> existingAlarmMap = new HashMap<>(existingAlarmList.size());
for (EmsRecordAlarmData alarmData : existingAlarmList) {
existingAlarmMap.put(alarmData.getObjId(), alarmData);
}
List<Long> pendingIds = new ArrayList<>();
for (Long objId : uniqueObjIds) {
int requestTimes = requestCountMap.get(objId);
EmsRecordAlarmData existing = existingAlarmMap.get(objId);
if (existing == null) {
result.setMissingCount(result.getMissingCount() + 1);
result.getMissingIds().add(objId);
result.setMissingCount(result.getMissingCount() + requestTimes);
addRepeatedId(result.getMissingIds(), objId, requestTimes);
continue;
}
if (Objects.equals(existing.getAlarmStatus(), EmsAlarmStatusConstants.HANDLED)) {
result.setAlreadyHandledCount(result.getAlreadyHandledCount() + 1);
result.getAlreadyHandledIds().add(objId);
result.setAlreadyHandledCount(result.getAlreadyHandledCount() + requestTimes);
addRepeatedId(result.getAlreadyHandledIds(), objId, requestTimes);
continue;
}
EmsRecordAlarmData alarmData = new EmsRecordAlarmData();
alarmData.setObjId(objId);
alarmData.setAlarmStatus(EmsAlarmStatusConstants.HANDLED);
alarmData.setOperationName(getUsername());
alarmData.setOperationTime(DateUtils.getNowDate());
alarmData.setConfirmUserId(getUserId());
alarmData.setUpdateTime(DateUtils.getNowDate());
// 只允许从“未处理”切到“已处理”,这样并发确认时第二次提交会拿到 0 行更新。
int updated = emsRecordAlarmDataMapper.markAlarmHandled(alarmData);
if (updated > 0) {
result.setUpdatedCount(result.getUpdatedCount() + updated);
result.getSuccessIds().add(objId);
} else {
result.setAlreadyHandledCount(result.getAlreadyHandledCount() + 1);
result.getAlreadyHandledIds().add(objId);
pendingIds.add(objId);
if (requestTimes > 1) {
// 同一个请求体重复提交相同告警时,只让首个 ID 参与更新,其余保持与逐条处理一致:视为已处理。
result.setAlreadyHandledCount(result.getAlreadyHandledCount() + requestTimes - 1);
addRepeatedId(result.getAlreadyHandledIds(), objId, requestTimes - 1);
}
}
if (!pendingIds.isEmpty()) {
Date operationTime = DateUtils.getNowDate();
EmsRecordAlarmData alarmData = new EmsRecordAlarmData();
alarmData.setAlarmStatus(EmsAlarmStatusConstants.HANDLED);
alarmData.setOperationName(getUsername());
alarmData.setOperationTime(operationTime);
alarmData.setConfirmUserId(getUserId());
alarmData.setUpdateTime(operationTime);
int updated = emsRecordAlarmDataMapper.markAlarmHandledBatch(pendingIds, alarmData);
if (updated != pendingIds.size()) {
throw new ServiceException("告警状态已被并发修改,请刷新后重试");
}
result.setUpdatedCount(result.getUpdatedCount() + updated);
result.getSuccessIds().addAll(pendingIds);
}
return result;
}
/**
* ID
*
* <p> objId
* 便 requestCount </p>
*/
private void addRepeatedId(List<Long> targetIds, Long objId, int repeatTimes) {
for (int i = 0; i < repeatTimes; i++) {
targetIds.add(objId);
}
}
/**
*
*
@ -477,7 +512,7 @@ public class EmsRecordAlarmDataServiceImpl implements IEmsRecordAlarmDataService
case 8: // 气体浓度
return record.getConcentration();
default:
System.out.println("未知的监测字段: " + monitorField);
log.warn("未知的监测字段monitorField={}", monitorField);
return null;
}
}
@ -712,7 +747,7 @@ public class EmsRecordAlarmDataServiceImpl implements IEmsRecordAlarmDataService
// 第一层:批次内去重
List<EmsRecordAlarmData> deduplicatedList = performBatchDeduplication(alarmDataList);
System.out.println("批次内去重:原始 " + alarmDataList.size() + " 条,去重后 " + deduplicatedList.size() + " 条");
log.debug("批次内去重完成originalCount={}, deduplicatedCount={}", alarmDataList.size(), deduplicatedList.size());
// 第二层:数据库去重并插入
int insertedCount = 0;
@ -723,7 +758,7 @@ public class EmsRecordAlarmDataServiceImpl implements IEmsRecordAlarmDataService
// 获取记录时间现在存储的是recordTime
Date recordTime = alarmData.getCollectTime();
if (recordTime == null) {
System.out.println("跳过无记录时间的异常数据");
log.warn("跳过无记录时间的异常数据monitorId={}, cause={}", alarmData.getMonitorId(), alarmData.getCause());
continue;
}
@ -744,21 +779,18 @@ public class EmsRecordAlarmDataServiceImpl implements IEmsRecordAlarmDataService
int result = insertEmsRecordAlarmData(alarmData);
if (result > 0) {
insertedCount++;
System.out.println("成功插入异常数据 - 设备:" + alarmData.getMonitorId() +
", 原因:" + alarmData.getCause() +
", 记录时间:" + alarmData.getCollectTime() +
", 数值:" + alarmData.getAlarmData());
log.info("成功插入异常数据monitorId={}, cause={}, collectTime={}, alarmData={}",
alarmData.getMonitorId(), alarmData.getCause(), alarmData.getCollectTime(), alarmData.getAlarmData());
}
} else {
System.out.println("跳过重复异常数据 - 设备:" + alarmData.getMonitorId() +
", 原因:" + alarmData.getCause() +
", 记录时间:" + alarmData.getCollectTime() +
", 10分钟内已存在 " + existingCount + " 条相同记录");
log.debug("跳过重复异常数据monitorId={}, cause={}, collectTime={}, duplicateCount={}",
alarmData.getMonitorId(), alarmData.getCause(), alarmData.getCollectTime(), existingCount);
}
} catch (Exception e) {
System.err.println("插入异常数据时发生错误: " + e.getMessage());
e.printStackTrace();
log.error("插入异常数据失败monitorId={}, cause={}, collectTime={}",
alarmData.getMonitorId(), alarmData.getCause(), alarmData.getCollectTime(), e);
throw new ServiceException("异常数据入库失败,请检查采集数据和告警规则配置");
}
}
@ -788,7 +820,7 @@ public class EmsRecordAlarmDataServiceImpl implements IEmsRecordAlarmDataService
if (uniqueKey != null && !uniqueRecords.containsKey(uniqueKey)) {
uniqueRecords.put(uniqueKey, alarmData);
} else if (uniqueKey != null) {
System.out.println("批次内发现重复记录,已跳过 - " + uniqueKey);
log.debug("批次内发现重复记录已跳过uniqueKey={}", uniqueKey);
}
}

@ -1,6 +1,7 @@
package org.dromara.ems.record.service.impl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.ems.base.domain.EmsAlarmActionStep;
import org.dromara.ems.base.domain.EmsAlarmNotifyGroup;
@ -21,6 +22,7 @@ import java.util.List;
* @date 2024-05-15
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class EmsRecordAlarmRuleServiceImpl implements IEmsRecordAlarmRuleService
{
@ -132,14 +134,14 @@ public class EmsRecordAlarmRuleServiceImpl implements IEmsRecordAlarmRuleService
// 级联删除措施步骤(会自动删除关联的图片文件)
int deletedSteps = emsAlarmActionStepService.deleteEmsAlarmActionStepByObjIds(stepIds);
System.out.println("删除异常规则 " + alarmRule.getRuleName() + " 关联的 " + deletedSteps + " 个措施步骤");
log.info("删除异常规则关联措施步骤ruleName={}, deletedSteps={}", alarmRule.getRuleName(), deletedSteps);
}
// 3. 最后删除异常规则本身
int result = emsRecordAlarmRuleMapper.deleteEmsRecordAlarmRuleByObjId(objId);
if (result > 0) {
System.out.println("成功删除异常规则: " + alarmRule.getRuleName() + " (ID: " + objId + ")");
log.info("成功删除异常规则ruleName={}, objId={}", alarmRule.getRuleName(), objId);
}
return result;

@ -1,7 +1,9 @@
package org.dromara.ems.record.service.impl;
import cn.hutool.http.HttpStatus;
import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.ems.base.domain.EmsBaseMonitorInfo;
@ -23,7 +25,9 @@ import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -34,6 +38,7 @@ import java.util.stream.Collectors;
* @date 2025-04-28
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class RecordIotenvInstantServiceImpl implements IRecordIotenvInstantService
{
@ -49,6 +54,32 @@ public class RecordIotenvInstantServiceImpl implements IRecordIotenvInstantServi
private static final String BEGIN_RECORD_TIME_KEY = "beginRecordTime";
private static final String END_RECORD_TIME_KEY = "endRecordTime";
private static final int LATEST_TABLE_LOOKBACK_DAYS = 7;
private static final int MULTI_MONITOR_QUERY_THREADS = 20;
private static final long EXECUTOR_SHUTDOWN_TIMEOUT_SECONDS = 30L;
private static final BigDecimal SENSOR_POSITIVE_MIN_VALUE = BigDecimal.ZERO;
/**
* 湿/沿 79
*
*/
private static final BigDecimal ENV_SENSOR_VALID_MAX_VALUE = new BigDecimal("79");
/**
* 沿 80 80
*/
private static final BigDecimal VIBRATION_SENSOR_VALID_MAX_VALUE = new BigDecimal("80");
/**
* 线
* new 线/线
*/
private final ExecutorService multiMonitorQueryExecutor = Executors.newFixedThreadPool(
MULTI_MONITOR_QUERY_THREADS,
runnable -> {
Thread thread = new Thread(runnable);
thread.setName("iotenv-multi-query-" + thread.getId());
thread.setDaemon(true);
return thread;
}
);
/**
*
@ -315,47 +346,63 @@ public class RecordIotenvInstantServiceImpl implements IRecordIotenvInstantServi
* @return
*/
private List<RecordIotenvInstant> selectMultipleMonitorData(List<String> tableNames, RecordIotenvInstant recordIotenvInstant,String[] monitorIds) {
// 创建线程池
int threadCount = Math.min(monitorIds.length,20);
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
if (monitorIds == null || monitorIds.length == 0) {
return new ArrayList<>();
}
//创建任务列表
List<Future<List<RecordIotenvInstant>>> futures = new ArrayList<>();
// 每个测点一个独立查询对象,避免并发任务共享同一个 BO 导致 monitorId 被互相覆盖。
List<Future<List<RecordIotenvInstant>>> futures = new ArrayList<>();
for (String monitorId : monitorIds) {
Future<List<RecordIotenvInstant>> future = multiMonitorQueryExecutor.submit(() -> {
RecordIotenvInstant query = new RecordIotenvInstant();
BeanUtils.copyProperties(recordIotenvInstant, query);
query.setMonitorId(monitorId);
query.setMonitorIds(null);
return recordIotenvInstantMapper.selectRecordIotenvInstantListFromTables(tableNames, query);
});
futures.add(future);
}
// 为每个设备创建查询任务
for(String monitorId : monitorIds){
Future<List<RecordIotenvInstant>> future
= executorService.submit(() -> {
// 创建新的查询对象,避免并发修改
RecordIotenvInstant query = new RecordIotenvInstant();
BeanUtils.copyProperties(recordIotenvInstant, query);
query.setMonitorId(monitorId);
query.setMonitorIds(null); // 清空数组使用单个ID查询
List<RecordIotenvInstant> result = new ArrayList<>();
for (Future<List<RecordIotenvInstant>> future : futures) {
try {
List<RecordIotenvInstant> partialResult = future.get();
if (partialResult != null && !partialResult.isEmpty()) {
result.addAll(partialResult);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
cancelUnfinishedTasks(futures);
throw new ServiceException("多测点数据查询被中断,请稍后重试");
} catch (ExecutionException e) {
cancelUnfinishedTasks(futures);
log.error("多测点数据查询失败", e);
throw new ServiceException("多测点数据查询失败,请稍后重试");
}
}
return result;
}
// 执行查询
return recordIotenvInstantMapper
.selectRecordIotenvInstantListFromTables(tableNames, query);
});
futures.add(future);
}
private void cancelUnfinishedTasks(List<Future<List<RecordIotenvInstant>>> futures) {
for (Future<List<RecordIotenvInstant>> future : futures) {
if (!future.isDone()) {
future.cancel(true);
}
}
}
// 收集所有查询结果
List<RecordIotenvInstant> result = new ArrayList<>();
for (Future<List<RecordIotenvInstant>> future : futures) {
try {
List<RecordIotenvInstant> partialResult = future.get();
if (partialResult != null && !partialResult.isEmpty()) {
result.addAll(partialResult);
}
} catch (Exception e) {
// 记录异常但继续处理其他结果
e.printStackTrace();
}
}
// 关闭线程池
executorService.shutdown();
return result;
@PreDestroy
public void shutdownMultiMonitorQueryExecutor() {
multiMonitorQueryExecutor.shutdown();
try {
if (!multiMonitorQueryExecutor.awaitTermination(EXECUTOR_SHUTDOWN_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
// 应用停机时不再等待长查询,避免进程无法及时退出。
multiMonitorQueryExecutor.shutdownNow();
}
} catch (InterruptedException e) {
multiMonitorQueryExecutor.shutdownNow();
Thread.currentThread().interrupt();
}
}
@Override
@ -597,7 +644,7 @@ public class RecordIotenvInstantServiceImpl implements IRecordIotenvInstantServi
}).collect(Collectors.toList());
}
/** 判断指定振动参数是否有效:>0且<80 */
/** 判断指定振动参数是否有效:大于0且小于振动字段历史有效上限 */
private boolean isValidVibrationParam(RecordIotenvInstant record, String vibrationParam) {
BigDecimal value = null;
switch (vibrationParam) {
@ -616,7 +663,7 @@ public class RecordIotenvInstantServiceImpl implements IRecordIotenvInstantServi
default:
return false;
}
return value != null && value.compareTo(BigDecimal.ZERO) > 0 && value.compareTo(new BigDecimal("80")) < 0;
return isValidVibrationValue(value, VIBRATION_SENSOR_VALID_MAX_VALUE);
}
/** 判断记录对于指定类型是否有效 */
@ -635,33 +682,37 @@ public class RecordIotenvInstantServiceImpl implements IRecordIotenvInstantServi
}
}
/** 判断温度是否有效:>0且<=79 */
/** 判断温度是否有效:大于0且不超过环境类字段历史有效上限 */
private boolean isValidTemperature(BigDecimal temperature) {
return temperature != null && temperature.compareTo(BigDecimal.ZERO) > 0 && temperature.compareTo(new BigDecimal("79")) <= 0;
return isValidEnvSensorValue(temperature);
}
/** 判断湿度是否有效:>0且<=79 */
/** 判断湿度是否有效:大于0且不超过环境类字段历史有效上限 */
private boolean isValidHumidity(BigDecimal humidity) {
return humidity != null && humidity.compareTo(BigDecimal.ZERO) > 0 && humidity.compareTo(new BigDecimal("79")) <= 0;
return isValidEnvSensorValue(humidity);
}
/** 判断噪声是否有效:>0且<=79 */
/** 判断噪声是否有效:大于0且不超过环境类字段历史有效上限 */
private boolean isValidNoise(BigDecimal noise) {
return noise != null && noise.compareTo(BigDecimal.ZERO) > 0 && noise.compareTo(new BigDecimal("79")) <= 0;
return isValidEnvSensorValue(noise);
}
/** 判断是否有有效的振动数据:>0且<80 */
/** 判断是否有有效的振动数据:大于0且小于振动字段历史有效上限 */
private boolean hasValidVibrationData(RecordIotenvInstant record) {
BigDecimal upperLimit = new BigDecimal("80");
return isValidVibrationValue(record.getVibrationSpeed(), upperLimit) ||
isValidVibrationValue(record.getVibrationDisplacement(), upperLimit) ||
isValidVibrationValue(record.getVibrationAcceleration(), upperLimit) ||
isValidVibrationValue(record.getVibrationTemp(), upperLimit);
return isValidVibrationValue(record.getVibrationSpeed(), VIBRATION_SENSOR_VALID_MAX_VALUE) ||
isValidVibrationValue(record.getVibrationDisplacement(), VIBRATION_SENSOR_VALID_MAX_VALUE) ||
isValidVibrationValue(record.getVibrationAcceleration(), VIBRATION_SENSOR_VALID_MAX_VALUE) ||
isValidVibrationValue(record.getVibrationTemp(), VIBRATION_SENSOR_VALID_MAX_VALUE);
}
/** 判断振动值是否有效:>0且<80 */
/** 判断环境类传感器值是否有效,先保留历史上限,后续可迁移到配置表。 */
private boolean isValidEnvSensorValue(BigDecimal value) {
return value != null && value.compareTo(SENSOR_POSITIVE_MIN_VALUE) > 0 && value.compareTo(ENV_SENSOR_VALID_MAX_VALUE) <= 0;
}
/** 判断振动值是否有效大于0且小于指定上限 */
private boolean isValidVibrationValue(BigDecimal value, BigDecimal upperLimit) {
return value != null && value.compareTo(BigDecimal.ZERO) > 0 && value.compareTo(upperLimit) < 0;
return value != null && value.compareTo(SENSOR_POSITIVE_MIN_VALUE) > 0 && value.compareTo(upperLimit) < 0;
}
/** 判断记录是否有任何有效数据 */

@ -3,6 +3,8 @@ package org.dromara.ems.report.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -31,6 +33,7 @@ public class EmsReportPointDnb extends BaseEntity
/**
*
*/
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/**

@ -3,6 +3,8 @@ package org.dromara.ems.report.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -31,6 +33,7 @@ public class EmsReportPointSteam extends BaseEntity
/**
*
*/
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/**

@ -3,6 +3,8 @@ package org.dromara.ems.report.domain;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -30,6 +32,7 @@ public class EmsReportPointWater extends BaseEntity
/**
*
*/
@TableId(value = "obj_id", type = IdType.ASSIGN_ID)
private Long objId;
/**

@ -17,6 +17,7 @@ import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;
/**
* Service
@ -46,6 +47,12 @@ public class TempBoardServiceImpl implements ITempBoardService {
private static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
/**
*
* MyBatis XML 使 ${tableName} Mapper Service
*/
private static final Pattern TABLE_NAME_PATTERN = Pattern.compile("^record_iotenv_instant_\\d{8}$");
/** 线程安全的静态格式化器,替代每次 new SimpleDateFormat */
private static final DateTimeFormatter FMT = DateTimeFormatter.ofPattern(DATETIME_FORMAT);
@ -73,7 +80,20 @@ public class TempBoardServiceImpl implements ITempBoardService {
if (diffMs > maxRangeMs) {
throw new ServiceException("查询跨度不能超过" + MAX_QUERY_DAYS + "天,请缩小范围");
}
return partitionService.resolveTables(query.getStartTime(), query.getEndTime());
List<String> tableNames = partitionService.resolveTables(query.getStartTime(), query.getEndTime());
validateResolvedTableNames(tableNames);
return tableNames;
}
/**
* ${tableName}
*/
private void validateResolvedTableNames(List<String> tableNames) {
for (String tableName : tableNames) {
if (!TABLE_NAME_PATTERN.matcher(tableName).matches()) {
throw new ServiceException("非法分表名称:" + tableName);
}
}
}
/** Date → 格式化字符串(兼容旧接口) */

@ -134,11 +134,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<insert id="insertEmsBaseMonitorInfo"
parameterType="org.dromara.ems.base.domain.EmsBaseMonitorInfo"
useGeneratedKeys="true"
keyProperty="objId">
parameterType="org.dromara.ems.base.domain.EmsBaseMonitorInfo">
insert into ems_base_monitor_info
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="objId != null">obj_id,</if>
<if test="parentId != null">parent_id,</if>
<if test="monitorCode != null and monitorCode != ''">monitor_code,</if>
<if test="monitorName != null">monitor_name,</if>
@ -187,6 +186,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="objId != null">#{objId},</if>
<if test="parentId != null">#{parentId},</if>
<if test="monitorCode != null and monitorCode != ''">#{monitorCode},</if>
<if test="monitorName != null">#{monitorName},</if>

@ -138,6 +138,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where rad.obj_id = #{objId}
</select>
<select id="selectEmsRecordAlarmDataByObjIds" resultMap="EmsRecordAlarmDataResult">
<include refid="selectEmsRecordAlarmDataVo"/>
where rad.obj_id in
<foreach item="objId" collection="objIds" open="(" separator="," close=")">
#{objId}
</foreach>
</select>
<insert id="insertEmsRecordAlarmData" parameterType="EmsRecordAlarmData" useGeneratedKeys="true" keyProperty="objId">
insert into ems_record_alarm_data
<trim prefix="(" suffix=")" suffixOverrides=",">
@ -242,6 +250,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
and alarm_status &lt;&gt; #{alarmStatus}
</update>
<update id="markAlarmHandledBatch">
update ems_record_alarm_data
set alarm_status = #{alarmData.alarmStatus},
operation_name = #{alarmData.operationName},
operation_time = #{alarmData.operationTime},
confirm_user_id = #{alarmData.confirmUserId},
update_time = #{alarmData.updateTime}
where obj_id in
<foreach item="objId" collection="objIds" open="(" separator="," close=")">
#{objId}
</foreach>
and alarm_status &lt;&gt; #{alarmData.alarmStatus}
</update>
<delete id="deleteEmsRecordAlarmDataByObjId" parameterType="Long">
delete from ems_record_alarm_data where obj_id = #{objId}
</delete>

@ -128,7 +128,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</delete>
<!-- 使用 UNION ALL 从多个表查询物联网数据列表 -->
<!--
使用 UNION ALL 从多个分表查询物联网数据列表。
注意tableName 只能来自 RecordIotenvPartitionService/Service 层按 record_iotenv_instant_yyyyMMdd 白名单生成的结果,
禁止把前端或外部系统传入的原始字符串直接传给本 Mapper避免 ${tableName} 产生 SQL 注入。
-->
<select id="selectRecordIotenvInstantListFromTables" resultMap="RecordIotenvInstantResult">
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
SELECT t.objid, t.monitorId, t.temperature, t.humidity, t.illuminance, t.noise, t.concentration,
@ -169,9 +173,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND (t.humidity IS NULL OR t.humidity BETWEEN 0 AND 79)
AND (t.noise IS NULL OR t.noise BETWEEN 0 AND 79)
<!-- 过滤虚拟设备忽略is_ammeter为0的虚拟设备 -->
-- AND (ebmi.is_ammeter IS NULL OR ebmi.is_ammeter != '0')
<!-- 根据设备类型过滤掉负责字段为0的数据 -->
<!-- 对于没有设备信息的记录保留所有非0数据 -->
AND (
@ -192,54 +193,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ORDER BY recodeTime DESC, objid DESC
</select>
<!-- 待测试limit测试一 使用 UNION ALL 从多个表查询物联网数据列表 ,具有分页功能(可能会在查询完所有数据后才limit需测试)-->
<!-- <select id="selectFromTablesWithPage" resultMap="RecordIotenvInstantResult">
select * from (
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
(SELECT t.objid, t.monitorId, t.temperature, t.humidity, t.illuminance, t.noise, t.concentration,
t.vibration_speed, t.vibration_displacement, t.vibration_acceleration, t.vibration_temp,
t.collectTime, t.recodeTime,
ebmi.monitor_name
FROM ${tableName} t
left join ems_base_monitor_info ebmi on t.monitorId = ebmi.monitor_code
<where>
<if test="recordIotenvInstant.monitorId != null and recordIotenvInstant.monitorId != ''"> and monitorId = #{recordIotenvInstant.monitorId}</if>
<if test="recordIotenvInstant.temperature != null "> and temperature = #{recordIotenvInstant.temperature}</if>
<if test="recordIotenvInstant.humidity != null "> and humidity = #{recordIotenvInstant.humidity}</if>
<if test="recordIotenvInstant.illuminance != null "> and illuminance = #{recordIotenvInstant.illuminance}</if>
<if test="recordIotenvInstant.noise != null "> and noise = #{recordIotenvInstant.noise}</if>
<if test="recordIotenvInstant.concentration != null "> and concentration = #{recordIotenvInstant.concentration}</if>
<if test="recordIotenvInstant.vibrationSpeed != null "> and vibration_speed = #{recordIotenvInstant.vibrationSpeed}</if>
<if test="recordIotenvInstant.vibrationDisplacement != null "> and vibration_displacement = #{recordIotenvInstant.vibrationDisplacement}</if>
<if test="recordIotenvInstant.vibrationAcceleration != null "> and vibration_acceleration = #{recordIotenvInstant.vibrationAcceleration}</if>
<if test="recordIotenvInstant.vibrationTemp != null "> and vibration_temp = #{recordIotenvInstant.vibrationTemp}</if>
<if test="recordIotenvInstant.collectTime != null "> and collectTime = #{recordIotenvInstant.collectTime}</if>
<if test="recordIotenvInstant.recodeTime != null "> and recodeTime = #{recordIotenvInstant.recodeTime}</if>
<if test="recordIotenvInstant.params.beginRecordTime!= null and recordIotenvInstant.params.endRecordTime != null">
AND recodeTime BETWEEN #{recordIotenvInstant.params.beginRecordTime} AND #{recordIotenvInstant.params.endRecordTime}
</if>
<if test="recordIotenvInstant.monitorIds != null and recordIotenvInstant.monitorIds.length > 0">
AND monitorId IN
<foreach collection="recordIotenvInstant.monitorIds" item="monitorId" open="(" separator="," close=")">
#{monitorId}
</foreach>
</if>
</where>
</foreach>
)AS combined_data
ORDER BY recodeTime desc
LIMIT #{offset}, #{pageSize}
</select> -->
<!-- 测试二: 使用 UNION ALL 从多个表查询物联网数据列表 ,具有分页功能-->
<!--
SQL Server 2012+ 分页:保持跨分表 UNION 后的全局排序语义,
用 OFFSET/FETCH 替代外层 ROW_NUMBER减少一层全量行号物化。
-->
<select id="selectFromTablesWithPage" resultMap="RecordIotenvInstantResult">
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY recodeTime DESC,objid DESC) as row_num
SELECT *
FROM (
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
(SELECT t.objid, t.monitorId, t.temperature, t.humidity, t.illuminance, t.noise, t.concentration,
@ -274,15 +233,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
</if>
<!-- 过滤异常数据:温度、湿度、噪声范围 [1, 79] -->
<!-- 过滤异常数据:温度、湿度、噪声范围 [0, 79] -->
<!-- 这里沿用范围过滤和空值判断,避免无意义的数据点拖慢历史查询。 -->
AND (t.temperature IS NULL OR t.temperature BETWEEN 0 AND 79)
AND (t.humidity IS NULL OR t.humidity BETWEEN 0 AND 79)
AND (t.noise IS NULL OR t.noise BETWEEN 0 AND 79)
<!-- 过滤虚拟设备忽略is_ammeter为0的虚拟设备 -->
-- AND (ebmi.is_ammeter IS NULL OR ebmi.is_ammeter != '0')
<!-- 根据设备类型过滤掉负责字段为0的数据 -->
<!-- 对于没有设备信息的记录保留所有非0数据 -->
AND (
@ -320,8 +276,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
)
</foreach>
) AS all_data
) AS paged_data
WHERE row_num &gt; #{offset} AND row_num &lt;= (#{offset} + #{pageSize})
ORDER BY recodeTime DESC, objid DESC
OFFSET #{offset} ROWS FETCH NEXT #{pageSize} ROWS ONLY
</select>

@ -2,6 +2,11 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.ems.report.mapper.TempBoardMapper">
<!--
温度看板当前按 SQL Server 语法实现TOP / DATEDIFF / GETDATE / FORMAT / DATEADD 等)。
如后续需要兼容 MySQL/PostgreSQL应参照振动/位移看板的 _databaseId 分支统一改造,避免局部替换造成口径漂移。
-->
<!-- 公共字段片段:每个分表 SELECT 温度相关字段 + JOIN 测点名称 -->
<sql id="baseColumns">
t.monitorId,

Loading…
Cancel
Save