refactor: 重构设备参数查询逻辑使用Facade层
parent
6ada262bf2
commit
cbbe49407d
@ -0,0 +1,27 @@
|
||||
package com.aucma.base.mapper;
|
||||
|
||||
import com.aucma.base.domain.BaseDeviceParamVal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 统一旁路参数读取Mapper
|
||||
*/
|
||||
public interface DeviceParamReadFacadeMapper {
|
||||
|
||||
/**
|
||||
* 查询设备参数最新值
|
||||
*/
|
||||
BaseDeviceParamVal selectLatestParamValue(Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 查询时间点附近参数
|
||||
*/
|
||||
List<BaseDeviceParamVal> selectParamsByTimePoint(Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 查询参数历史明细
|
||||
*/
|
||||
List<BaseDeviceParamVal> selectHistoryParamValues(Map<String, Object> params);
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package com.aucma.base.service;
|
||||
|
||||
import com.aucma.base.domain.BaseDeviceParamVal;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 统一旁路参数读取能力
|
||||
*/
|
||||
public interface IDeviceParamReadFacade {
|
||||
|
||||
/**
|
||||
* 查询设备参数最新值
|
||||
*/
|
||||
BaseDeviceParamVal getLatestParamValue(String deviceCode, String paramCode, String paramName);
|
||||
|
||||
/**
|
||||
* 查询某个时间点附近的参数集
|
||||
*/
|
||||
List<BaseDeviceParamVal> listParamsByTimePoint(String deviceCode, Date snapshotTime, int windowSeconds);
|
||||
|
||||
/**
|
||||
* 对比两个时间点的参数差异
|
||||
*/
|
||||
List<Map<String, Object>> compareParamsByTimePoint(String deviceCode, Date timePoint1, Date timePoint2, int windowSeconds);
|
||||
|
||||
/**
|
||||
* 查询参数历史明细
|
||||
*/
|
||||
List<BaseDeviceParamVal> listHistoryParamValues(String deviceCode, String paramCode, String paramName,
|
||||
Date beginTime, Date endTime, Integer limit);
|
||||
|
||||
/**
|
||||
* 按参数名集合查询参数历史明细
|
||||
*/
|
||||
List<BaseDeviceParamVal> listHistoryParamValuesByNames(String deviceCode, List<String> paramNames,
|
||||
Date beginTime, Date endTime, Integer limit);
|
||||
|
||||
/**
|
||||
* 查询数值型历史值
|
||||
*/
|
||||
List<Double> listNumericHistoryValues(String deviceCode, String paramCode, Date beginTime, Date endTime);
|
||||
}
|
||||
@ -0,0 +1,209 @@
|
||||
package com.aucma.base.service.impl;
|
||||
|
||||
import com.aucma.base.domain.BaseDeviceParamVal;
|
||||
import com.aucma.base.mapper.DeviceParamReadFacadeMapper;
|
||||
import com.aucma.base.service.IDeviceParamReadFacade;
|
||||
import com.aucma.base.support.DeviceParamTableRouter;
|
||||
import com.aucma.common.utils.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* 统一旁路参数读取Service
|
||||
*/
|
||||
@Service
|
||||
public class DeviceParamReadFacadeImpl implements IDeviceParamReadFacade {
|
||||
|
||||
private static final int DEFAULT_TIME_POINT_WINDOW_SECONDS = 60;
|
||||
private static final int LATEST_LOOKBACK_MONTHS = 12;
|
||||
|
||||
@Autowired
|
||||
private DeviceParamReadFacadeMapper deviceParamReadFacadeMapper;
|
||||
|
||||
@Autowired
|
||||
private DeviceParamTableRouter deviceParamTableRouter;
|
||||
|
||||
@Override
|
||||
public BaseDeviceParamVal getLatestParamValue(String deviceCode, String paramCode, String paramName) {
|
||||
Map<String, Object> params = buildQueryParams(deviceCode, paramCode, paramName, buildLatestBeginTime(), new Date());
|
||||
// 为什么这样做:旁路消费方不应该继续感知 OLD 单表、NEW 月表和跨月范围,
|
||||
// latest 口径在这里统一收口后,预警/安灯/报表才能保持一致。
|
||||
return deviceParamReadFacadeMapper.selectLatestParamValue(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BaseDeviceParamVal> listParamsByTimePoint(String deviceCode, Date snapshotTime, int windowSeconds) {
|
||||
if (StringUtils.isEmpty(deviceCode) || snapshotTime == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
int effectiveWindowSeconds = windowSeconds > 0 ? windowSeconds : DEFAULT_TIME_POINT_WINDOW_SECONDS;
|
||||
Date beginTime = addSeconds(snapshotTime, -effectiveWindowSeconds);
|
||||
Date endTime = addSeconds(snapshotTime, effectiveWindowSeconds);
|
||||
Map<String, Object> params = buildQueryParams(deviceCode, null, null, beginTime, endTime);
|
||||
params.put("snapshotTime", snapshotTime);
|
||||
// 为什么这样做:工艺快照的本质是“某时间点附近最近一次参数状态”,
|
||||
// 所以这里统一用时间窗口 + 双源合并,而不是让快照模块直接写死旧表。
|
||||
List<BaseDeviceParamVal> paramList = deviceParamReadFacadeMapper.selectParamsByTimePoint(params);
|
||||
return paramList != null ? paramList : Collections.<BaseDeviceParamVal>emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> compareParamsByTimePoint(String deviceCode, Date timePoint1, Date timePoint2, int windowSeconds) {
|
||||
List<BaseDeviceParamVal> beforeList = listParamsByTimePoint(deviceCode, timePoint1, windowSeconds);
|
||||
List<BaseDeviceParamVal> afterList = listParamsByTimePoint(deviceCode, timePoint2, windowSeconds);
|
||||
if (beforeList.isEmpty() && afterList.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Map<String, BaseDeviceParamVal> beforeMap = toParamIndex(beforeList);
|
||||
Map<String, BaseDeviceParamVal> afterMap = toParamIndex(afterList);
|
||||
TreeMap<String, Map<String, Object>> compareMap = new TreeMap<String, Map<String, Object>>();
|
||||
fillCompareMap(compareMap, beforeMap, true);
|
||||
fillCompareMap(compareMap, afterMap, false);
|
||||
return new ArrayList<Map<String, Object>>(compareMap.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BaseDeviceParamVal> listHistoryParamValues(String deviceCode, String paramCode, String paramName,
|
||||
Date beginTime, Date endTime, Integer limit) {
|
||||
Map<String, Object> params = buildQueryParams(deviceCode, paramCode, paramName, beginTime, endTime);
|
||||
params.put("limit", limit);
|
||||
List<BaseDeviceParamVal> paramList = deviceParamReadFacadeMapper.selectHistoryParamValues(params);
|
||||
return paramList != null ? paramList : Collections.<BaseDeviceParamVal>emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BaseDeviceParamVal> listHistoryParamValuesByNames(String deviceCode, List<String> paramNames,
|
||||
Date beginTime, Date endTime, Integer limit) {
|
||||
if (paramNames == null || paramNames.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Map<String, Object> params = buildQueryParams(deviceCode, null, null, beginTime, endTime);
|
||||
params.put("paramNames", paramNames);
|
||||
params.put("limit", limit);
|
||||
List<BaseDeviceParamVal> paramList = deviceParamReadFacadeMapper.selectHistoryParamValues(params);
|
||||
return paramList != null ? paramList : Collections.<BaseDeviceParamVal>emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Double> listNumericHistoryValues(String deviceCode, String paramCode, Date beginTime, Date endTime) {
|
||||
List<BaseDeviceParamVal> historyList = listHistoryParamValues(deviceCode, paramCode, null, beginTime, endTime, 1000);
|
||||
if (historyList.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<Double> values = new ArrayList<Double>(historyList.size());
|
||||
for (BaseDeviceParamVal history : historyList) {
|
||||
Double numericValue = parseNumeric(history.getParamValue());
|
||||
if (numericValue != null) {
|
||||
values.add(numericValue);
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private Map<String, Object> buildQueryParams(String deviceCode, String paramCode, String paramName, Date beginTime, Date endTime) {
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.put("deviceCode", trimToNull(deviceCode));
|
||||
params.put("paramCode", trimToNull(paramCode));
|
||||
params.put("paramName", trimToNull(paramName));
|
||||
params.put("beginTime", beginTime);
|
||||
params.put("endTime", endTime);
|
||||
params.put("tableSuffixes", resolveReadTableSuffixes(beginTime, endTime));
|
||||
return params;
|
||||
}
|
||||
|
||||
private List<String> resolveReadTableSuffixes(Date beginTime, Date endTime) {
|
||||
if (beginTime == null || endTime == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return deviceParamTableRouter.resolveReadTableSuffixes(beginTime, endTime);
|
||||
}
|
||||
|
||||
private Date buildLatestBeginTime() {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.MONTH, -LATEST_LOOKBACK_MONTHS);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
private Date addSeconds(Date baseTime, int seconds) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(baseTime);
|
||||
calendar.add(Calendar.SECOND, seconds);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
private Map<String, BaseDeviceParamVal> toParamIndex(List<BaseDeviceParamVal> paramList) {
|
||||
Map<String, BaseDeviceParamVal> paramIndex = new LinkedHashMap<String, BaseDeviceParamVal>();
|
||||
for (BaseDeviceParamVal paramVal : paramList) {
|
||||
paramIndex.put(resolveParamKey(paramVal), paramVal);
|
||||
}
|
||||
return paramIndex;
|
||||
}
|
||||
|
||||
private void fillCompareMap(TreeMap<String, Map<String, Object>> compareMap, Map<String, BaseDeviceParamVal> paramMap, boolean beforeFlag) {
|
||||
for (Map.Entry<String, BaseDeviceParamVal> entry : paramMap.entrySet()) {
|
||||
BaseDeviceParamVal paramVal = entry.getValue();
|
||||
Map<String, Object> row = compareMap.get(entry.getKey());
|
||||
if (row == null) {
|
||||
row = new LinkedHashMap<String, Object>();
|
||||
row.put("paramCode", trimToNull(paramVal.getParamCode()));
|
||||
row.put("paramName", trimToNull(paramVal.getParamName()));
|
||||
compareMap.put(entry.getKey(), row);
|
||||
}
|
||||
if (beforeFlag) {
|
||||
row.put("beforeValue", paramVal.getParamValue());
|
||||
} else {
|
||||
row.put("afterValue", paramVal.getParamValue());
|
||||
}
|
||||
row.put("isChanged", isChanged(row.get("beforeValue"), row.get("afterValue")) ? "Y" : "N");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isChanged(Object beforeValue, Object afterValue) {
|
||||
String beforeText = beforeValue == null ? null : beforeValue.toString();
|
||||
String afterText = afterValue == null ? null : afterValue.toString();
|
||||
if (beforeText == null) {
|
||||
return afterText != null;
|
||||
}
|
||||
return !beforeText.equals(afterText);
|
||||
}
|
||||
|
||||
private String resolveParamKey(BaseDeviceParamVal paramVal) {
|
||||
if (paramVal == null) {
|
||||
return "";
|
||||
}
|
||||
if (StringUtils.isNotEmpty(paramVal.getParamCode())) {
|
||||
return "CODE:" + paramVal.getParamCode();
|
||||
}
|
||||
return "NAME:" + trimToNull(paramVal.getParamName());
|
||||
}
|
||||
|
||||
private String trimToNull(String text) {
|
||||
if (text == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = text.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
|
||||
private Double parseNumeric(String paramValue) {
|
||||
if (StringUtils.isEmpty(paramValue)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return new BigDecimal(paramValue.trim()).doubleValue();
|
||||
} catch (NumberFormatException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,125 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.aucma.base.mapper.DeviceParamReadFacadeMapper">
|
||||
|
||||
<resultMap type="BaseDeviceParamVal" id="BaseDeviceParamValResult">
|
||||
<result property="recordId" column="record_id"/>
|
||||
<result property="paramCode" column="param_code"/>
|
||||
<result property="deviceCode" column="device_code"/>
|
||||
<result property="deviceId" column="device_id"/>
|
||||
<result property="paramName" column="param_name"/>
|
||||
<result property="paramValue" column="param_value"/>
|
||||
<result property="collectTime" column="collect_time"/>
|
||||
<result property="recordTime" column="record_time"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="baseSelectColumns">
|
||||
record_id || '' AS record_id,
|
||||
param_code,
|
||||
device_code,
|
||||
device_id,
|
||||
param_name,
|
||||
param_value,
|
||||
collect_time,
|
||||
record_time
|
||||
</sql>
|
||||
|
||||
<sql id="commonFilters">
|
||||
<if test="deviceCode != null and deviceCode != ''">
|
||||
AND device_code = #{deviceCode}
|
||||
</if>
|
||||
<if test="paramCode != null and paramCode != ''">
|
||||
AND param_code = #{paramCode}
|
||||
</if>
|
||||
<if test="paramName != null and paramName != ''">
|
||||
AND param_name = #{paramName}
|
||||
</if>
|
||||
<if test="paramNames != null and paramNames.size() > 0">
|
||||
AND param_name IN
|
||||
<foreach item="paramNameItem" collection="paramNames" open="(" separator="," close=")">
|
||||
#{paramNameItem}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="beginTime != null">
|
||||
AND NVL(record_time, collect_time) >= #{beginTime}
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND NVL(record_time, collect_time) <= #{endTime}
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<sql id="mergedParamSource">
|
||||
<trim suffixOverrides="UNION ALL">
|
||||
SELECT <include refid="baseSelectColumns"/>
|
||||
FROM BASE_DEVICE_PARAM_VAL
|
||||
WHERE 1 = 1
|
||||
<include refid="commonFilters"/>
|
||||
UNION ALL
|
||||
<if test="tableSuffixes != null and tableSuffixes.size() > 0">
|
||||
<foreach item="suffix" collection="tableSuffixes" separator=" UNION ALL ">
|
||||
SELECT <include refid="baseSelectColumns"/>
|
||||
FROM BASE_DEVICE_PARAM_VAL_${suffix}
|
||||
WHERE 1 = 1
|
||||
<include refid="commonFilters"/>
|
||||
</foreach>
|
||||
</if>
|
||||
</trim>
|
||||
</sql>
|
||||
|
||||
<select id="selectLatestParamValue" parameterType="java.util.Map" resultMap="BaseDeviceParamValResult">
|
||||
SELECT *
|
||||
FROM (
|
||||
SELECT merged_param.*,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY merged_param.device_code,
|
||||
NVL(merged_param.param_code, merged_param.param_name)
|
||||
ORDER BY NVL(merged_param.record_time, merged_param.collect_time) DESC,
|
||||
merged_param.record_id DESC
|
||||
) AS rn
|
||||
FROM (
|
||||
<include refid="mergedParamSource"/>
|
||||
) merged_param
|
||||
)
|
||||
WHERE rn = 1
|
||||
AND ROWNUM = 1
|
||||
</select>
|
||||
|
||||
<select id="selectParamsByTimePoint" parameterType="java.util.Map" resultMap="BaseDeviceParamValResult">
|
||||
SELECT *
|
||||
FROM (
|
||||
SELECT merged_param.*,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY NVL(merged_param.param_code, merged_param.param_name)
|
||||
ORDER BY ABS((NVL(merged_param.record_time, merged_param.collect_time) - #{snapshotTime}) * 86400),
|
||||
NVL(merged_param.record_time, merged_param.collect_time) DESC,
|
||||
merged_param.record_id DESC
|
||||
) AS rn
|
||||
FROM (
|
||||
<include refid="mergedParamSource"/>
|
||||
) merged_param
|
||||
)
|
||||
WHERE rn = 1
|
||||
ORDER BY NVL(param_code, param_name), NVL(record_time, collect_time) DESC
|
||||
</select>
|
||||
|
||||
<select id="selectHistoryParamValues" parameterType="java.util.Map" resultMap="BaseDeviceParamValResult">
|
||||
SELECT *
|
||||
FROM (
|
||||
SELECT merged_param.*,
|
||||
ROW_NUMBER() OVER (
|
||||
ORDER BY NVL(merged_param.record_time, merged_param.collect_time) ASC,
|
||||
merged_param.record_id ASC
|
||||
) AS row_num
|
||||
FROM (
|
||||
<include refid="mergedParamSource"/>
|
||||
) merged_param
|
||||
)
|
||||
<if test="limit != null">
|
||||
WHERE row_num <= #{limit}
|
||||
</if>
|
||||
ORDER BY row_num
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue