fix:优化历史数据分页

main
HuangHuiKang 7 hours ago
parent aa7c6da293
commit 62eea2d16a

@ -183,11 +183,13 @@ public class DeviceController {
@GetMapping("/historyRecord") @GetMapping("/historyRecord")
@Operation(summary = "历史记录查询") @Operation(summary = "历史记录查询")
// @PreAuthorize("@ss.hasPermission('iot:device:query')") // @PreAuthorize("@ss.hasPermission('iot:device:query')")
public CommonResult<List<Map<String, Object>>> historyRecord(@RequestParam("deviceId") Long deviceId, public CommonResult<PageResult<Map<String, Object>>> historyRecord(@RequestParam("deviceId") Long deviceId,
@RequestParam(name = "collectionStartTime", required = false) String collectionStartTime, @RequestParam(name = "collectionStartTime", required = false) String collectionStartTime,
@RequestParam(name = "collectionEndTime", required = false) String collectionEndTime @RequestParam(name = "collectionEndTime", required = false) String collectionEndTime,
@RequestParam(name = "pageNo", required = false, defaultValue = "1") Integer page,
@RequestParam(name = "pageSize", required = false, defaultValue = "10") Integer pageSize
) throws JsonProcessingException { ) throws JsonProcessingException {
List<Map<String, Object>> deviceContactModelDO=deviceService.historyRecord(deviceId,collectionStartTime,collectionEndTime); PageResult<Map<String, Object>> deviceContactModelDO=deviceService.historyRecord(deviceId,collectionStartTime,collectionEndTime,page,pageSize);
return success(deviceContactModelDO); return success(deviceContactModelDO);
} }

@ -123,7 +123,7 @@ public interface DeviceService {
Map<String, List<Map<String, Object>>> singleDevice(Long deviceId) throws JsonProcessingException; Map<String, List<Map<String, Object>>> singleDevice(Long deviceId) throws JsonProcessingException;
List<Map<String, Object>> historyRecord(Long deviceId,String collectionStartTime, String collectionEndTime); PageResult<Map<String, Object>> historyRecord(Long deviceId,String collectionStartTime, String collectionEndTime,Integer page,Integer size);
Map<Long, Map<String, Object>> createDeviceDataMap(Long deviceId); Map<Long, Map<String, Object>> createDeviceDataMap(Long deviceId);

@ -108,6 +108,8 @@ public class DeviceServiceImpl implements DeviceService {
@Resource @Resource
private DeviceOperationRecordMapper deviceOperationRecordMapper; private DeviceOperationRecordMapper deviceOperationRecordMapper;
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public DeviceDO createDevice(DeviceSaveReqVO createReqVO) { public DeviceDO createDevice(DeviceSaveReqVO createReqVO) {
@ -689,78 +691,107 @@ public class DeviceServiceImpl implements DeviceService {
} }
@Override @Override
public List<Map<String, Object>> historyRecord(Long deviceId,String collectionStartTime, String collectionEndTime) { public PageResult<Map<String, Object>> historyRecord(Long deviceId, String collectionStartTime, String collectionEndTime,Integer page,
Integer pageSize) {
List<Map<String, Object>> resultList = new ArrayList<>(); List<Map<String, Object>> resultList = new ArrayList<>();
if (deviceId == null) {
return null;
}
try { try {
// 1. 获取设备数据列表 // 1. 获取设备数据列表
List<Map<String, Object>> deviceDataList = tdengineService.getstDeviceDataOrderByTimeDesc(deviceId,collectionStartTime,collectionEndTime,null); List<Map<String, Object>> deviceDataList = tdengineService.getstDeviceDataOrderByTimeDescPage(
deviceId, collectionStartTime, collectionEndTime, page, pageSize
);
// 2. 获取属性类型映射 long total = tdengineService.queryDeviceDataTotal(deviceId, collectionStartTime, collectionEndTime);
if (deviceDataList.isEmpty()) {
return null;
}
// 2. 获取属性类型映射 (ID -> Name) 并构建缓存,避免重复数据库查询
Map<Long, String> idToNameMap = deviceAttributeTypeMapper.selectList() Map<Long, String> idToNameMap = deviceAttributeTypeMapper.selectList()
.stream() .stream()
.collect(Collectors.toMap( .collect(Collectors.toMap(DeviceAttributeTypeDO::getId, DeviceAttributeTypeDO::getName));
DeviceAttributeTypeDO::getId,
DeviceAttributeTypeDO::getName // 额外缓存数字ID -> 名称防止同一个ID多次查询数据库
)); Map<Long, String> attributeTypeCache = new HashMap<>();
ObjectMapper objectMapper = new ObjectMapper();
// 3. 遍历每个时间点的数据 // 3. 遍历每条设备数据
for (Map<String, Object> deviceData : deviceDataList) { for (Map<String, Object> deviceData : deviceDataList) {
String queryDataJson = (String) deviceData.get("queryData"); String queryDataJson = (String) deviceData.get("queryData");
Timestamp timestamp = (Timestamp) deviceData.get("timestamp"); Timestamp timestamp = (Timestamp) deviceData.get("timestamp");
if (StringUtils.isNotBlank(queryDataJson) && timestamp != null) { if (StringUtils.isBlank(queryDataJson) || timestamp == null) {
List<Map<String, Object>> dataList = new ObjectMapper().readValue( continue; // 跳过无效数据
queryDataJson, }
new TypeReference<List<Map<String, Object>>>() {}
List<Map<String, Object>> dataList = objectMapper.readValue(
queryDataJson, new TypeReference<List<Map<String, Object>>>() {}
); );
// 按属性类型分组 // 4. 按属性类型分组
Map<String, List<Map<String, Object>>> groupedData = new LinkedHashMap<>(); Map<String, List<Map<String, Object>>> groupedData = new LinkedHashMap<>();
for (Map<String, Object> data : dataList) { for (Map<String, Object> data : dataList) {
String attributeTypeName = "其他"; String attributeTypeName = "其他";
String typeStr = (String) data.get("attributeType"); Object typeObj = data.get("attributeType");
if (typeStr != null) {
if (typeObj != null) {
String typeStr = typeObj.toString();
try { try {
// 尝试当作数字 ID
Long typeId = Long.parseLong(typeStr);
// 先从缓存查
if (attributeTypeCache.containsKey(typeId)) {
attributeTypeName = attributeTypeCache.get(typeId);
} else {
// 查数据库
String nameFromDb = idToNameMap.get(typeId);
if (nameFromDb != null) {
attributeTypeName = nameFromDb;
} else {
attributeTypeName = typeStr; // 查不到就用原值
}
attributeTypeCache.put(typeId, attributeTypeName);
}
} catch (NumberFormatException e) {
// 不是数字,直接用原字符串
attributeTypeName = typeStr; attributeTypeName = typeStr;
} catch (Exception e) {
attributeTypeName = "未知";
} }
} }
// 构建属性数据 Map
Map<String, Object> simplifiedData = new HashMap<>(); Map<String, Object> simplifiedData = new HashMap<>();
simplifiedData.put("addressValue", data.get("addressValue")); simplifiedData.put("addressValue", data.get("addressValue"));
simplifiedData.put("attributeName", data.get("attributeName")); simplifiedData.put("attributeName", data.get("attributeName"));
groupedData groupedData.computeIfAbsent(attributeTypeName, k -> new ArrayList<>())
.computeIfAbsent(attributeTypeName, k -> new ArrayList<>())
.add(simplifiedData); .add(simplifiedData);
} }
// 创建当前时间点的Map // 5. 构建时间点 Map
Map<String, Object> timePointData = new LinkedHashMap<>(); Map<String, Object> timePointData = new LinkedHashMap<>(groupedData);
// 添加属性分组
for (Map.Entry<String, List<Map<String, Object>>> entry : groupedData.entrySet()) {
timePointData.put(entry.getKey(), entry.getValue());
}
// 添加收集时间
timePointData.put("collectTime", timestamp.toString()); timePointData.put("collectTime", timestamp.toString());
resultList.add(timePointData); resultList.add(timePointData);
} }
} return new PageResult<>(resultList, total);
} catch (Exception e) { } catch (Exception e) {
System.out.println("处理设备数据时发生异常: " + e.getMessage()); log.error("处理设备数据时发生异常", e);
return PageResult.empty();
}
} }
return resultList;
}
private void validateDeviceAttributeExists(Long id) { private void validateDeviceAttributeExists(Long id) {

@ -266,6 +266,96 @@ public class TDengineService {
} }
} }
/**
*
* @param id ID
* @return
*/
@DS("tdengine")
public List<Map<String, Object>> getstDeviceDataOrderByTimeDescPage(Long id,String StartTime, String EndTime,Integer page,
Integer pageSize) {
String tableName = "d_" + id;
StringBuilder sqlBuilder = new StringBuilder();
List<Object> params = new ArrayList<>();
sqlBuilder.append("SELECT ts, query_data FROM besure.").append(tableName).append(" WHERE 1=1");
if (StartTime != null) {
// 直接将时间字符串拼接到SQL中
sqlBuilder.append(" AND ts >= '").append(StartTime).append("'");
}
if (EndTime != null) {
sqlBuilder.append(" AND ts <= '").append(EndTime).append("'");
}
sqlBuilder.append(" ORDER BY ts DESC");
// 分页处理
if (page != null && pageSize != null && page > 0 && pageSize > 0) {
int offset = (page - 1) * pageSize;
sqlBuilder.append(" LIMIT ").append(offset).append(",").append(pageSize);
}
try {
return jdbcTemplate.query(sqlBuilder.toString(), new RowMapper<Map<String, Object>>() {
@Override
public Map<String, Object> mapRow(ResultSet rs, int rowNum) throws SQLException {
Map<String, Object> result = new HashMap<>();
result.put("timestamp", rs.getTimestamp("ts"));
result.put("deviceId", id);
// 读取 query_data二进制字段
byte[] blob = rs.getBytes("query_data");
result.put("queryData", decodeQueryData(blob));
return result;
}
});
} catch (Exception e) {
// log.error("查询设备" + id + "的最新数据时发生异常", e);
// e.printStackTrace();
return Collections.singletonList(createEmptyResult(id));
}
}
/**
*
*
* @param deviceId ID
* @param startTime
* @param endTime
* @return
*/
@DS("tdengine")
public long queryDeviceDataTotal(Long deviceId, String startTime, String endTime) {
if (deviceId == null) {
return 0L;
}
String tableName = "d_" + deviceId;
StringBuilder countSql = new StringBuilder("SELECT COUNT(*) FROM besure." + tableName + " WHERE 1=1");
if (startTime != null) {
countSql.append(" AND ts >= '").append(startTime).append("'");
}
if (endTime != null) {
countSql.append(" AND ts <= '").append(endTime).append("'");
}
try {
Long total = jdbcTemplate.queryForObject(countSql.toString(), Long.class);
return total != null ? total : 0L;
} catch (Exception e) {
log.error("查询设备 {} 总条数异常", deviceId, e);
return 0L;
}
}
/** /**
* TDengine * TDengine
* *

Loading…
Cancel
Save