From 611cece8cd129d955b31f496f99f443ebcae0a36 Mon Sep 17 00:00:00 2001 From: lishuai Date: Thu, 26 Sep 2024 16:26:49 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BC=93=E5=AD=98=E6=B8=85?= =?UTF-8?q?=E9=99=A4=E5=8A=9F=E8=83=BD=202024=E5=B9=B49=E6=9C=8826?= =?UTF-8?q?=E6=97=A516:26:43?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/AlarmRuleServiceImpl.java | 8 +- .../quartz/timetask/task/ThingStatusTask.java | 32 ++- .../IotThingMenuConfigController.java | 6 +- .../listener/QueueDeviceEventListener.java | 175 ++++++++----- .../listener/ThingChangedEventListener.java | 41 +++ ...ingChangedUpdateRelationEventListener.java | 12 +- .../impl/SysTenantDetailServiceImpl.java | 10 +- .../thing/thing/cache/service/CacheInit.java | 22 +- .../thing/thing/cache/service/ThingCache.java | 233 +++++++++++------- .../service/ThingManageContextService.java | 11 +- .../impl/ThingManageContextServiceImpl.java | 32 +-- .../impl/IotThingDictRelationServiceImpl.java | 58 +++-- .../impl/IotThingEntityServiceImpl.java | 115 +++++++-- .../thing/model/dto/IotThingModelDTO.java | 2 + .../model/param/DistributeModelParam.java | 2 - .../model/service/IotThingModelService.java | 2 +- .../impl/IotThingModelServiceImpl.java | 48 ++-- .../IotThingRelationDetailController.java | 18 +- .../IotThingRelationDetailService.java | 6 +- .../IotThingRelationDetailServiceImpl.java | 218 ++++++++++++---- .../impl/IotThingRelationRootServiceImpl.java | 63 +++-- 21 files changed, 756 insertions(+), 358 deletions(-) diff --git a/modules/alarm/src/main/java/com/thing/alarm/alarm/service/impl/AlarmRuleServiceImpl.java b/modules/alarm/src/main/java/com/thing/alarm/alarm/service/impl/AlarmRuleServiceImpl.java index 48f528f..62dbbf1 100644 --- a/modules/alarm/src/main/java/com/thing/alarm/alarm/service/impl/AlarmRuleServiceImpl.java +++ b/modules/alarm/src/main/java/com/thing/alarm/alarm/service/impl/AlarmRuleServiceImpl.java @@ -28,6 +28,7 @@ import com.thing.sys.biz.mapper.SysUserMapper; import com.thing.thing.context.service.ThingManageContextService; import com.thing.thing.dictRelation.param.IotThingDictRelationParamDTO; import com.thing.thing.entity.dto.IotThingEntityDTO; +import com.thing.thing.model.dto.IotThingModelDTO; import jakarta.annotation.Resource; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -165,11 +166,10 @@ public class AlarmRuleServiceImpl extends BaseServiceImpl optionalList = thingManageContextService.findModelByCodes(thingCodeSet).orElseGet(Collections::emptyList); + List optionalList = thingManageContextService.findModelByCodes(thingCodeSet).orElseGet(Collections::emptyList); Map modelMap =optionalList.stream().collect(Collectors.toMap( - k-> k.get(CacheNameEnum.ModelField.THING_MODEL_CODE.getField()).asText(), - v-> v.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asLong())); - + IotThingModelDTO::getCode, + IotThingModelDTO::getId)); originalList.forEach(item -> item.setEntityId(modelMap.get(item.getThingCode()))); } diff --git a/modules/quartz/src/main/java/com/thing/quartz/timetask/task/ThingStatusTask.java b/modules/quartz/src/main/java/com/thing/quartz/timetask/task/ThingStatusTask.java index a6add85..d59febe 100644 --- a/modules/quartz/src/main/java/com/thing/quartz/timetask/task/ThingStatusTask.java +++ b/modules/quartz/src/main/java/com/thing/quartz/timetask/task/ThingStatusTask.java @@ -9,7 +9,8 @@ import com.thing.common.data.tskv.TsKvDTO; import com.thing.common.tskv.service.TsKvService; import com.thing.thing.cache.service.ThingCache; import com.thing.thing.context.service.ThingManageContextService; -import com.thing.thing.model.dto.IotThingModelDTO; +import com.thing.thing.model.entity.IotThingModelEntity; +import com.thing.thing.model.service.IotThingModelService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; @@ -22,6 +23,8 @@ import java.util.List; import java.util.Optional; import java.util.stream.Collectors; +import static com.thing.thing.cache.service.CacheInit.KEY; + /** * 设备在线离线 * @@ -41,6 +44,7 @@ public class ThingStatusTask implements ITask { private final ThingManageContextService thingManageContextService; private final TsKvService tsKvService; private final ThingCache cache; + private final IotThingModelService modelService; /** * 执行定时任务接口 @@ -59,7 +63,7 @@ public class ThingStatusTask implements ITask { List codes = optionalList.get().stream().map(s -> s.get(CacheNameEnum.ModelField.THING_MODEL_CODE.getField()).asText()).toList(); List lastTsKvList = tsKvService.findLatestByCodesAndAttrs(codes, null, true); //处理 - List statusList = optionalList.get().stream() + List statusList = optionalList.get().stream() .map(item -> { // IotThingModelDTO iotThingModelDTO = JacksonUtil.convertValue(item, IotThingModelDTO.class); //找到最大时间的属性 @@ -74,28 +78,32 @@ public class ThingStatusTask implements ITask { boolean isOffline = System.currentTimeMillis() - tsKvDTO.getTs() > TIME_INTERVAL; item.put(CacheNameEnum.ModelField.THING_MODEL_STATUS.getField(),isOffline ? ThingStatus.OFFLINE.getCode() : ThingStatus.ONLINE.getCode()); item.put(CacheNameEnum.ModelField.THING_MODEL_STATUS_TS.getField(),new Date(tsKvDTO.getTs()).getTime()); - //更新实体设备状态 - List entityNodes = cache.findKeyMap(CacheNameEnum.THING_ENTITY, item.get(CacheNameEnum.ModelField.THING_MODEL_CODE.getField()).asText()); + //更新实体设备状态:这里需要精确匹配 + List entityNodes = cache.findMapAccurateKeys(CacheNameEnum.THING_ENTITY, item.get(CacheNameEnum.ModelField.THING_MODEL_CODE.getField()).asText()); if(CollectionUtils.isNotEmpty(entityNodes)){ for (ObjectNode entityNode : entityNodes) { + entityNode.put(CacheNameEnum.EntityField.THING_ENTITY_STATUS.getField() ,isOffline ? ThingStatus.OFFLINE.getCode() : ThingStatus.ONLINE.getCode()); - cache.updateKeyMap(CacheNameEnum.THING_ENTITY + + cache.updateAccurateKeyMap(CacheNameEnum.THING_ENTITY ,entityNode.get(CacheNameEnum.EntityField.THING_ENTITY_TENANT_CODE.getField()).asText() - + ":" + entityNode.get(CacheNameEnum.EntityField.THING_ENTITY_CODE.getField()).asText() - + ":" + entityNode.get(CacheNameEnum.EntityField.THING_ENTITY_ID.getField()).asText(),entityNode); + + KEY + entityNode.get(CacheNameEnum.EntityField.THING_ENTITY_CODE.getField()).asText() + + KEY + entityNode.get(CacheNameEnum.EntityField.THING_ENTITY_ID.getField()).asText(),entityNode); } } } //更新物模型 - cache.updateKeyMap(CacheNameEnum.THING_MODEL + cache.updateAccurateKeyMap(CacheNameEnum.THING_MODEL , item.get(CacheNameEnum.ModelField.THING_MODEL_CODE.getField()).asText() - + ":" + item.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asText(),item); - return JacksonUtil.convertValue(item, IotThingModelDTO.class); + + KEY + item.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asText(),item); + return JacksonUtil.convertValue(item, IotThingModelEntity.class); }).collect(Collectors.toList()); - //修改状态 - thingManageContextService.saveModelBatch(statusList); + if(CollectionUtils.isNotEmpty(statusList)){ + //修改状态 + modelService.saveOrUpdateBatch(statusList); + } log.info("设备在线离线 statusTask end"); } diff --git a/modules/thing/src/main/java/com/thing/device/menu/controller/IotThingMenuConfigController.java b/modules/thing/src/main/java/com/thing/device/menu/controller/IotThingMenuConfigController.java index dc79ffc..650f662 100644 --- a/modules/thing/src/main/java/com/thing/device/menu/controller/IotThingMenuConfigController.java +++ b/modules/thing/src/main/java/com/thing/device/menu/controller/IotThingMenuConfigController.java @@ -79,9 +79,11 @@ public class IotThingMenuConfigController { if (jsonArray != null && !jsonArray.isEmpty()) { for (int i = 0; i < jsonArray.size(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); - Long id = jsonObject.getLong("id"); + Long id = jsonObject.getLong("toId"); IotThingRelationRootDTO relationRootDTO = relationRootService.findById(id); - jsonObject.put("name", relationRootDTO.getName()); + if(ObjectUtil.isNotNull(relationRootDTO)){ + jsonObject.put("name", relationRootDTO.getName()); + } } data.setMenuConfig(jsonArray.toString()); } diff --git a/modules/thing/src/main/java/com/thing/listener/QueueDeviceEventListener.java b/modules/thing/src/main/java/com/thing/listener/QueueDeviceEventListener.java index 9b69e33..2e2370f 100644 --- a/modules/thing/src/main/java/com/thing/listener/QueueDeviceEventListener.java +++ b/modules/thing/src/main/java/com/thing/listener/QueueDeviceEventListener.java @@ -3,7 +3,6 @@ package com.thing.listener; import cn.hutool.core.collection.CollectionUtil; import com.fasterxml.jackson.databind.node.ObjectNode; import com.thing.common.cache.constants.CacheNameEnum; -import com.thing.common.core.constants.Constant; import com.thing.common.core.enumeration.GateWayStatus; import com.thing.common.core.enumeration.QueueOriginType; import com.thing.common.core.enumeration.TemplateMark; @@ -19,7 +18,6 @@ import com.thing.thing.entity.dto.IotThingViewDTO; import com.thing.thing.entity.entity.IotThingEntity; import com.thing.thing.entity.service.IotThingEntityService; import com.thing.thing.model.dto.IotThingModelDTO; -import com.thing.thing.model.dto.ModelDetailDTO; import com.thing.thing.model.entity.IotThingModelEntity; import com.thing.thing.model.service.IotThingModelService; import com.thing.transport.api.adaptor.JsonConverter; @@ -31,9 +29,12 @@ import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import java.util.*; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; import java.util.stream.Collectors; +import static com.thing.thing.cache.service.CacheInit.KEY; + @Slf4j @Component @RequiredArgsConstructor @@ -45,9 +46,18 @@ public class QueueDeviceEventListener { private final ThingCache thingCache; + + private final ReentrantLock lock = new ReentrantLock(); + @EventListener(QueueDeviceEvent.class) public void onDeviceEvent(QueueDeviceEvent event) { List msgList = event.getList(); + if(CollectionUtils.isEmpty(msgList)){ + return; + } + if (!lock.tryLock()) { + return; // 如果无法获取锁,退出处理 + } try { List validMsgList = msgList.stream() .filter(item -> Objects.nonNull(item.getTenantCode()) @@ -56,7 +66,7 @@ public class QueueDeviceEventListener { if (CollectionUtil.isEmpty(validMsgList)) { return; } - //先根据物模型编码去重 + //根据物编码聚合,再根据用户编码聚合 Map>> codeMapList = validMsgList.stream() .collect(Collectors.groupingBy(QueueMsgDTO::getThingCode, Collectors.groupingBy(QueueMsgDTO::getTenantCode))); //物模型插入 @@ -74,12 +84,15 @@ public class QueueDeviceEventListener { Long tenantCode = thingEntry.getKey(); QueueMsgDTO queueMsgDTO = thingEntry.getValue().get(0); //物模型缓存查询 - List list = thingModelService.findList(CacheNameEnum.ModelField.THING_MODEL_CREATE_DATE.getField(), - Constant.DESC, thingCode, null, null, null, null, null, null, null); + List list = thingCache.findMapAccurateKey(CacheNameEnum.THING_MODEL, thingCode); //缓存存在,更新,否则插入 if (CollectionUtils.isNotEmpty(list)) { IotThingModelEntity modelEntity = JacksonUtil.convertValue(list.get(0), IotThingModelEntity.class); + if(StringUtils.isBlank(modelEntity.getRealType())){ + modelEntity.setRealType("1"); + } updateModelList.add(modelEntity); +// updateModelCache(updateModelList); } else { String origin = QueueOriginType.AUTO_DATA_SYNC.name().equals(queueMsgDTO.getOrigin()) || QueueOriginType.MANUAL_DATA_SYNC.name().equals(queueMsgDTO.getOrigin()) @@ -92,21 +105,16 @@ public class QueueDeviceEventListener { .setAuthNum(0L) .setStatusTs(DateTimeUtils.getCurrentTime()) .setOrigin(origin); -// modelEntity.setId(IdUtil.getSnowflake().nextId()) -// .setCreateDate(DateTimeUtils.getCurrentTime()) -// .setCreateDate(DateTimeUtils.getCurrentTime()); insertModelList.add(modelEntity); } //物实体的构建 if (!Objects.equals(queueMsgDTO.getTenantCode(), 1001L)) { - List entityServiceList = entityService.findList(CacheNameEnum.EntityField.THING_ENTITY_CREATE_DATE.getField(), Constant.DESC, thingCode, null, tenantCode, - null, null, null, null, null, null); - if (CollectionUtils.isNotEmpty(entityServiceList)) { + List entityServiceList = thingCache.findMapAccurate2Key(CacheNameEnum.THING_ENTITY, thingCode,String.valueOf(tenantCode)); + if (CollectionUtils.isEmpty(entityServiceList)) { IotThingEntity newThingEntity = createThingEntity(thingCode, queueMsgDTO.getTenantCode(), queueMsgDTO.getCompanyId(), queueMsgDTO.getDeptId()); insertEntityList.add(newThingEntity); } } - } } //更新老的物模型 @@ -115,37 +123,33 @@ public class QueueDeviceEventListener { } //更新物实体的模型:uniqueModelList有值,物实体不一定有值 List distinctStudentFile = new ArrayList<>(); - if (CollectionUtils.isNotEmpty(insertModelList)) { - //物实体的插入和缓存更新 - if (CollectionUtils.isNotEmpty(insertEntityList)) { - distinctStudentFile.addAll(insertEntityList.stream() - .collect(Collectors.collectingAndThen( - Collectors.toCollection(() -> - new TreeSet<>(Comparator.comparing(o -> o.getCode() + ";" + o.getTenantCode()))), ArrayList::new))); - } + //物实体的插入和缓存更新 + if (CollectionUtils.isNotEmpty(insertEntityList)) { + distinctStudentFile.addAll(insertEntityList.stream() + .collect(Collectors.collectingAndThen( + Collectors.toCollection(() -> + new TreeSet<>(Comparator.comparing(o -> o.getCode() + ";" + o.getTenantCode()))), ArrayList::new))); } //更新物模型和物实体的缓存 insertModelList.forEach(item -> { long count = distinctStudentFile.stream().filter(e -> StringUtils.equals(e.getCode(), item.getCode())).count(); - List keyMap = thingCache.findKeyMap(CacheNameEnum.THING_ENTITY, item.getCode()); + List keyMap = thingCache.findMapAccurateKey(CacheNameEnum.THING_ENTITY, item.getCode()); item.setAuthNum(count + CollectionUtils.size(keyMap)); }); if(CollectionUtils.isNotEmpty(insertModelList)){ - try { - thingModelService.saveOrUpdateBatch(insertModelList); - } catch (Exception e) { - } + thingModelService.saveOrUpdateBatch(insertModelList); updateModelCache(insertModelList); } if(CollectionUtils.isNotEmpty(distinctStudentFile)){ - try { - entityService.saveOrUpdateBatch(distinctStudentFile); - } catch (Exception e) { - } + entityService.saveOrUpdateBatch(distinctStudentFile); updateEntityCache(distinctStudentFile); } } catch (Exception e) { log.error("设备保存失败: {}", e.getMessage(), e); + }finally { + if (lock.isHeldByCurrentThread()) { + lock.unlock(); + } } } @@ -156,58 +160,107 @@ public class QueueDeviceEventListener { if(CollectionUtils.isNotEmpty(topicMap)){ Map modelMap = modelList.stream().collect(Collectors.toMap( model -> model.get(CacheNameEnum.ModelField.THING_MODEL_CODE.getField()).asText() - + ":" + model.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asText() + + KEY + model.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asText() , Function.identity())); thingCache.putMap(CacheNameEnum.THING_MODEL, modelMap); }else{ for (ObjectNode item : modelList) { //更新物模型的缓存 - thingCache.updateKeyMap(CacheNameEnum.THING_MODEL + thingCache.updateAccurateKeyMap(CacheNameEnum.THING_MODEL , item.get(CacheNameEnum.ModelField.THING_MODEL_CODE.getField()).asText() - + ":" + item.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asText(), item); + + KEY + item.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asText(), item); } } } + private void updateOneModelCache(IotThingModelEntity insertModelList) { + IotThingModelDTO iotThingModelDTOS = ConvertUtils.sourceToTarget(insertModelList, IotThingModelDTO.class); + ObjectNode nodes = JsonConverter.convertToJsonObjectObjectNode(iotThingModelDTOS); + //更新物模型的缓存 + thingCache.updateAccurateKeyMap(CacheNameEnum.THING_MODEL + , nodes.get(CacheNameEnum.ModelField.THING_MODEL_CODE.getField()).asText() + + KEY + nodes.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asText(), nodes); + } + private void updateEntityCache(List distinctStudentFile) { //更新物实体缓存 - List entityList = distinctStudentFile.stream().map(e -> { - ObjectNode modelMap = thingCache.findAccurateObjectNode(CacheNameEnum.THING_MODEL, e.getCode()); - return new IotThingViewDTO() - .setLat(e.getLat()) - .setLon(e.getLon()) - .setTags(e.getTags()) - .setDeptIds(e.getDeptIds()) - .setOrigin(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_ORIGIN.getField()).asText()) - .setTemplateMark(TemplateMark.NO.getValue()) - .setRealType("1") - .setImg(e.getImg()) - .setRemark(e.getRemark()) - .setEnableStatus(e.getEnableStatus()) - .setStatusTs(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_STATUS_TS.getField()).asLong()) - .setStatus(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_STATUS.getField()).asText()) - .setTenantCode(e.getTenantCode()) - .setCompanyId(e.getTenantCode()) - .setDeptId(e.getTenantCode()) - .setEntityType(e.getType()) - .setEntityName(e.getName()) - .setEntityCode(e.getCode()) - .setEntityId(e.getId()) - .setModelId(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asLong()) - .setCreateDate(e.getCreateDate()); - }).toList(); + List entityList = distinctStudentFile.stream() + .filter(e -> CollectionUtils.isNotEmpty(thingCache.findMapAccurateKey(CacheNameEnum.THING_MODEL, e.getCode()))) + .map(e -> { + List nodeList = thingCache.findMapAccurateKey(CacheNameEnum.THING_MODEL, e.getCode()); + ObjectNode modelMap = nodeList.get(0); + return new IotThingViewDTO() + .setLat(e.getLat()) + .setLon(e.getLon()) + .setTags(e.getTags()) + .setDeptIds(e.getDeptIds()) + .setOrigin(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_ORIGIN.getField()).asText()) + .setTemplateMark(TemplateMark.NO.getValue()) + .setRealType(e.getRealType()) + .setImg(e.getImg()) + .setRemark(e.getRemark()) + .setEnableStatus(e.getEnableStatus()) + .setStatusTs(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_STATUS_TS.getField()).asLong()) + .setStatus(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_STATUS.getField()).asText()) + .setTenantCode(e.getTenantCode()) + .setCompanyId(e.getTenantCode()) + .setDeptId(e.getTenantCode()) + .setEntityType(e.getType()) + .setEntityName(e.getName()) + .setEntityCode(e.getCode()) + .setEntityId(e.getId()) + .setModelId(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asLong()) + .setCreateDate(e.getCreateDate()); + }).toList(); List entityJsonList = JsonConverter.convertToJsonObjectListObjectNode(entityList); for (ObjectNode entityNode : entityJsonList) { - thingCache.updateKeyMap(CacheNameEnum.THING_ENTITY + thingCache.updateAccurateKeyMap(CacheNameEnum.THING_ENTITY , entityNode.get(CacheNameEnum.EntityField.THING_ENTITY_TENANT_CODE.getField()).asText() - + ":" + entityNode.get(CacheNameEnum.EntityField.THING_ENTITY_CODE.getField()).asText() - + ":" + entityNode.get(CacheNameEnum.EntityField.THING_ENTITY_ID.getField()).asText(), entityNode); + + KEY + entityNode.get(CacheNameEnum.EntityField.THING_ENTITY_CODE.getField()).asText() + + KEY + entityNode.get(CacheNameEnum.EntityField.THING_ENTITY_ID.getField()).asText(), entityNode); } } + private void updateOneEntityCache(IotThingEntity entity) { + + if(CollectionUtils.isNotEmpty(thingCache.findMapAccurateKey(CacheNameEnum.THING_MODEL, entity.getCode()))){ + return; + } + List nodeList = thingCache.findMapAccurateKey(CacheNameEnum.THING_MODEL, entity.getCode()); + ObjectNode modelMap = nodeList.get(0); + IotThingViewDTO iotThingViewDTO = new IotThingViewDTO() + .setLat(entity.getLat()) + .setLon(entity.getLon()) + .setTags(entity.getTags()) + .setDeptIds(entity.getDeptIds()) + .setOrigin(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_ORIGIN.getField()).asText()) + .setTemplateMark(TemplateMark.NO.getValue()) + .setRealType(entity.getRealType()) + .setImg(entity.getImg()) + .setRemark(entity.getRemark()) + .setEnableStatus(entity.getEnableStatus()) + .setStatusTs(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_STATUS_TS.getField()).asLong()) + .setStatus(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_STATUS.getField()).asText()) + .setTenantCode(entity.getTenantCode()) + .setCompanyId(entity.getTenantCode()) + .setDeptId(entity.getTenantCode()) + .setEntityType(entity.getType()) + .setEntityName(entity.getName()) + .setEntityCode(entity.getCode()) + .setEntityId(entity.getId()) + .setModelId(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asLong()) + .setCreateDate(entity.getCreateDate()); + ObjectNode entityNode = JsonConverter.convertToJsonObjectObjectNode(iotThingViewDTO); + + thingCache.updateAccurateKeyMap(CacheNameEnum.THING_ENTITY + , entityNode.get(CacheNameEnum.EntityField.THING_ENTITY_TENANT_CODE.getField()).asText() + + KEY + entityNode.get(CacheNameEnum.EntityField.THING_ENTITY_CODE.getField()).asText() + + KEY + entityNode.get(CacheNameEnum.EntityField.THING_ENTITY_ID.getField()).asText(), entityNode); + } + private IotThingEntity createThingEntity(String thingCode, Long tenantCode, Long companyId, Long deptId) { IotThingEntity entity = new IotThingEntity(); - // entity.setId(IdUtil.getSnowflake().nextId()); + // entity.setId(IdUtil.getSnowflake().nextId()); entity.setCode(thingCode); entity.setName(thingCode); entity.setEnableStatus("1"); diff --git a/modules/thing/src/main/java/com/thing/listener/ThingChangedEventListener.java b/modules/thing/src/main/java/com/thing/listener/ThingChangedEventListener.java index 22b275c..3998666 100644 --- a/modules/thing/src/main/java/com/thing/listener/ThingChangedEventListener.java +++ b/modules/thing/src/main/java/com/thing/listener/ThingChangedEventListener.java @@ -1,8 +1,14 @@ package com.thing.listener; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.mybatisflex.core.update.UpdateChain; +import com.thing.common.cache.constants.CacheNameEnum; +import com.thing.common.core.enumeration.TemplateMark; import com.thing.device.source.entity.IotThingSourceEntity; import com.thing.event.ThingChangedEvent; +import com.thing.thing.cache.service.CacheInit; +import com.thing.thing.cache.service.ThingCache; +import com.thing.thing.entity.dto.IotThingViewDTO; import com.thing.thing.entity.entity.IotThingEntity; import lombok.RequiredArgsConstructor; @@ -11,6 +17,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; +import java.util.List; + /** * @author siyang * @date 2024/9/10 10:34 @@ -21,6 +29,8 @@ import org.springframework.stereotype.Component; @RequiredArgsConstructor public class ThingChangedEventListener { + private final ThingCache thingCache; + @EventListener(ThingChangedEvent.class) public void onThingChangedEvent(ThingChangedEvent event) { IotThingEntity thing = event.getThing(); @@ -29,5 +39,36 @@ public class ThingChangedEventListener { .where(IotThingSourceEntity::getThingId).eq(thing.getId()) .and(IotThingSourceEntity::getTenantCode).eq(thing.getTenantCode()) .update(); + + thingCache.updateAccurateKeyEntity(CacheNameEnum.THING_ENTITY, + thing.getTenantCode()+ CacheInit.KEY+thing.getCode()+CacheInit.KEY+thing.getId(),convertIotThingViewDTO(thing)); + + } + + private IotThingViewDTO convertIotThingViewDTO(IotThingEntity entity){ + List nodeList = thingCache.findMapAccurateKey(CacheNameEnum.THING_MODEL, entity.getCode()); + ObjectNode modelMap = nodeList.get(0); + return new IotThingViewDTO() + .setLat(entity.getLat()) + .setLon(entity.getLon()) + .setTags(entity.getTags()) + .setDeptIds(entity.getDeptIds()) + .setOrigin(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_ORIGIN.getField()).asText()) + .setTemplateMark(TemplateMark.NO.getValue()) + .setRealType(entity.getRealType()) + .setImg(entity.getImg()) + .setRemark(entity.getRemark()) + .setEnableStatus(entity.getEnableStatus()) + .setStatusTs(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_STATUS_TS.getField()).asLong()) + .setStatus(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_STATUS.getField()).asText()) + .setTenantCode(entity.getTenantCode()) + .setCompanyId(entity.getTenantCode()) + .setDeptId(entity.getTenantCode()) + .setEntityType(entity.getType()) + .setEntityName(entity.getName()) + .setEntityCode(entity.getCode()) + .setEntityId(entity.getId()) + .setModelId(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asLong()) + .setCreateDate(entity.getCreateDate()); } } diff --git a/modules/thing/src/main/java/com/thing/listener/ThingChangedUpdateRelationEventListener.java b/modules/thing/src/main/java/com/thing/listener/ThingChangedUpdateRelationEventListener.java index a6a70ab..054a9d1 100644 --- a/modules/thing/src/main/java/com/thing/listener/ThingChangedUpdateRelationEventListener.java +++ b/modules/thing/src/main/java/com/thing/listener/ThingChangedUpdateRelationEventListener.java @@ -1,11 +1,14 @@ package com.thing.listener; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.thing.common.cache.constants.CacheNameEnum; import com.thing.event.ThingRelationDetailUpdateEvent; +import com.thing.thing.cache.service.CacheInit; import com.thing.thing.cache.service.ThingCache; import com.thing.thing.entity.entity.IotThingEntity; import com.thing.thing.relation.detail.entity.IotThingRelationDetailEntity; import com.thing.thing.relation.detail.service.IotThingRelationDetailService; +import com.thing.transport.api.adaptor.JsonConverter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; @@ -38,17 +41,20 @@ public class ThingChangedUpdateRelationEventListener { entity.setFromName(thing.getName()); } thingRelationDetailService.updateBatch(fromEntities); + //更新缓存 + fromEntities.forEach(entity -> cache.updateAccurateKeyEntity(CacheNameEnum.THING_DETAIL_RELATION, + entity.getRootId()+CacheInit.KEY+entity.getId()+CacheInit.KEY+entity.getRootThingId(),entity)); } - List toEntities = thingRelationDetailService.findByFromIdAndToId(null, thing.getId()); - if(CollectionUtils.isNotEmpty(toEntities)){ for (IotThingRelationDetailEntity entity : toEntities) { entity.setToName(thing.getName()); } thingRelationDetailService.updateBatch(toEntities); + //更新缓存 + toEntities.forEach(entity -> cache.updateAccurateKeyEntity(CacheNameEnum.THING_DETAIL_RELATION, + entity.getRootId()+CacheInit.KEY+entity.getId()+CacheInit.KEY+entity.getRootThingId(),entity)); } } - cache.clearTopic(CacheNameEnum.THING_DETAIL_RELATION); } } diff --git a/modules/thing/src/main/java/com/thing/sys/tenant/service/impl/SysTenantDetailServiceImpl.java b/modules/thing/src/main/java/com/thing/sys/tenant/service/impl/SysTenantDetailServiceImpl.java index 4f3c124..662ae11 100644 --- a/modules/thing/src/main/java/com/thing/sys/tenant/service/impl/SysTenantDetailServiceImpl.java +++ b/modules/thing/src/main/java/com/thing/sys/tenant/service/impl/SysTenantDetailServiceImpl.java @@ -8,6 +8,7 @@ import com.google.common.collect.Maps; import com.mybatisflex.core.keygen.impl.SnowFlakeIDKeyGenerator; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; +import com.thing.common.cache.constants.CacheNameEnum; import com.thing.common.core.constants.Constant; import com.thing.common.core.enumeration.*; import com.thing.common.core.exception.ErrorCode; @@ -46,9 +47,12 @@ import com.thing.sys.tenant.mapper.SysTenantGroupMapper; import com.thing.sys.tenant.mapper.SysTenantMapper; import com.thing.sys.tenant.service.SysTenantDetailService; import com.thing.sys.tenant.service.SysTenantGroupService; +import com.thing.thing.cache.service.CacheInit; import com.thing.thing.cache.service.ThingCache; import com.thing.thing.context.service.ThingManageContextService; +import com.thing.thing.entity.dto.IotThingEntityDTO; import com.thing.thing.entity.entity.IotThingEntity; +import com.thing.thing.model.dto.ModelDetailDTO; import com.thing.thing.model.entity.IotThingModelEntity; import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; @@ -423,8 +427,12 @@ public class SysTenantDetailServiceImpl extends BaseServiceImpl relationDetailMap = list.stream().collect(Collectors.toMap( r -> r.get(CacheNameEnum.RelationDetailField.THING_RELATION_DETAIL_ROOT_ID.getField()).asText() - + ":" + r.get(CacheNameEnum.RelationDetailField.THING_RELATION_DETAIL_ID.getField()).asText() - + ":" + r.get(CacheNameEnum.RelationDetailField.THING_RELATION_DETAIL_ROOT_THING_ID.getField()).asText(), + + KEY + r.get(CacheNameEnum.RelationDetailField.THING_RELATION_DETAIL_ID.getField()).asText() + + KEY + r.get(CacheNameEnum.RelationDetailField.THING_RELATION_DETAIL_ROOT_THING_ID.getField()).asText(), Function.identity() )); thingCache.putMap(CacheNameEnum.THING_DETAIL_RELATION, relationDetailMap); @@ -106,8 +108,8 @@ public class CacheInit { } Map rootMap = list.stream().collect(Collectors.toMap( r -> r.get(CacheNameEnum.RelationRootField.THING_RELATION_ROOT_GROUP_NAME.getField()).asText() - + ":" + r.get(CacheNameEnum.RelationRootField.THING_RELATION_ROOT_NAME.getField()).asText() - + ":" + r.get(CacheNameEnum.RelationRootField.THING_RELATION_ROOT_ID.getField()).asText(), + + KEY + r.get(CacheNameEnum.RelationRootField.THING_RELATION_ROOT_NAME.getField()).asText() + + KEY + r.get(CacheNameEnum.RelationRootField.THING_RELATION_ROOT_ID.getField()).asText(), r -> { r.put("fromId", "0"); r.put("rootId", r.get("id").asText()); @@ -137,9 +139,9 @@ public class CacheInit { d.get(CacheNameEnum.DictField.THING_DICT_ENTITY_ID.getField()).asLong())) .findFirst(); return first.get().get(CacheNameEnum.EntityField.THING_ENTITY_TENANT_CODE.getField()).asText() - + ":" + first.get().get(CacheNameEnum.EntityField.THING_ENTITY_CODE.getField()).asText() - + ":" + d.get(CacheNameEnum.DictField.THING_DICT_CODE.getField()).asText() - + ":" + d.get(CacheNameEnum.DictField.THING_DICT_ID.getField()).asText(); + + KEY + first.get().get(CacheNameEnum.EntityField.THING_ENTITY_CODE.getField()).asText() + + KEY + d.get(CacheNameEnum.DictField.THING_DICT_CODE.getField()).asText() + + KEY + d.get(CacheNameEnum.DictField.THING_DICT_ID.getField()).asText(); }, Function.identity())); thingCache.putMap(CacheNameEnum.THING_DICT_RELATION, dictMap); } @@ -152,8 +154,8 @@ public class CacheInit { && !Objects.isNull(entityDTO.get(CacheNameEnum.EntityField.THING_ENTITY_TENANT_CODE.getField()).asLong())) .collect(Collectors.toMap( entityDTO -> entityDTO.get(CacheNameEnum.EntityField.THING_ENTITY_TENANT_CODE.getField()).asText() - + ":" + entityDTO.get(CacheNameEnum.EntityField.THING_ENTITY_CODE.getField()).asText() - + ":" + entityDTO.get(CacheNameEnum.EntityField.THING_ENTITY_ID.getField()).asText() + + KEY + entityDTO.get(CacheNameEnum.EntityField.THING_ENTITY_CODE.getField()).asText() + + KEY + entityDTO.get(CacheNameEnum.EntityField.THING_ENTITY_ID.getField()).asText() , Function.identity() )); @@ -166,7 +168,7 @@ public class CacheInit { } Map modelMap = modelList.stream().collect(Collectors.toMap( model -> model.get(CacheNameEnum.ModelField.THING_MODEL_CODE.getField()).asText() - + ":" + model.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asText() + + KEY + model.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asText() ,Function.identity())); thingCache.putMap(CacheNameEnum.THING_MODEL, modelMap); } diff --git a/modules/thing/src/main/java/com/thing/thing/cache/service/ThingCache.java b/modules/thing/src/main/java/com/thing/thing/cache/service/ThingCache.java index 140a19d..fddbf0a 100644 --- a/modules/thing/src/main/java/com/thing/thing/cache/service/ThingCache.java +++ b/modules/thing/src/main/java/com/thing/thing/cache/service/ThingCache.java @@ -1,15 +1,17 @@ package com.thing.thing.cache.service; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.thing.transport.api.adaptor.JsonConverter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.MapUtils; -import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +import static com.thing.thing.cache.service.CacheInit.KEY; + @Slf4j @Component public final class ThingCache { @@ -17,21 +19,24 @@ public final class ThingCache { /** key 为 topic: code - JsonObject 为 模型 */ private final ConcurrentHashMap> thingMap = new ConcurrentHashMap<>(); + /** + * 用于初始化缓存的方法:不存在相同的key就会存入缓存中,存在就不覆盖 + * @param topic + * @param map + */ public void putMap(String topic, Map map) { if (!map.isEmpty()) { thingMap.computeIfAbsent(topic, k -> new ConcurrentHashMap<>()).putAll(map); } } - public List getTopicMap(String topic) { - ConcurrentHashMap map = thingMap.get(topic); - if (map == null || map.isEmpty()) { - return List.of(); - } - return map.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(Map.Entry::getValue).collect(Collectors.toList()); - } - public List findTopicMap(String topic, String key) { + /** + * 根据topic获取对应的map中 所有数据集合 + * @param topic + * @return + */ + public List getTopicMap(String topic) { ConcurrentHashMap map = thingMap.get(topic); if (map == null || map.isEmpty()) { return List.of(); @@ -39,47 +44,14 @@ public final class ThingCache { return map.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(Map.Entry::getValue).collect(Collectors.toList()); } - public List getTopicMap(String topic, String key) { - ConcurrentHashMap map = thingMap.get(topic); - if (map == null || map.isEmpty()) { - return List.of(); - } - return map.entrySet().stream() - .filter(entry -> StringUtils.contains(entry.getKey(), key)) - .sorted(Map.Entry.comparingByKey()) - .map(Map.Entry::getValue) - .toList(); - } - - public List getTopicMap(String topic, List keys) { - ConcurrentHashMap map = thingMap.get(topic); - if (map == null || map.isEmpty()) { - return List.of(); - } - return map.entrySet().stream() - .filter(entry -> keys.stream().anyMatch(key-> StringUtils.contains(entry.getKey(), key))) - .sorted(Map.Entry.comparingByKey()) - .map(Map.Entry::getValue) - .toList(); - } - - public List getTopicMap(String topic, int size) { - Map map = thingMap.get(topic); - if (map == null || map.isEmpty() || size <= 0) { - return List.of(); - } - return map.entrySet().stream().sorted(Map.Entry.comparingByKey()).limit(size).map(Map.Entry::getValue).collect(Collectors.toList()); - } - - public Map getMap(String topic, int size) { - Map map = thingMap.get(topic); - if (map == null || map.isEmpty() || size <= 0) { - return Map.of(); - } - return map.entrySet().stream().sorted(Map.Entry.comparingByKey()).limit(size).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } - - public List findKeyMap(String topic, String key) { + /** + * 根据 topic 获取 模糊匹配key的集合数据 + * 注意点:这个方法有个缺陷:当thingCode 相似的时候,会匹配到多个,比如 thingCode: 123456 和 thingCode: 123456789 + * @param topic + * @param key + * @return + */ + public List findMapLikeKey(String topic, String key) { ConcurrentHashMap valMap = thingMap.get(topic); if(MapUtils.isEmpty(valMap)){ return null; @@ -87,42 +59,104 @@ public final class ThingCache { return valMap.entrySet().stream().filter(entry -> entry.getKey().contains(key)).map(Map.Entry::getValue).collect(Collectors.toList()); } - /** - * 模糊匹配 + /** + * 根据 topic 获取 精确匹配key的集合数据 * @param topic * @param key * @return */ - public ObjectNode findObjectNode(String topic, String key) { + public List findMapAccurateKey(String topic, String key) { ConcurrentHashMap valMap = thingMap.get(topic); if(MapUtils.isEmpty(valMap)){ - return null; + return Collections.emptyList(); } - Optional first = valMap.entrySet().stream().filter(entry -> entry.getKey().contains(key)).map(Map.Entry::getValue).findFirst(); - return first.orElse(null); + return valMap.entrySet().stream().filter(entry -> + Arrays.asList(entry.getKey().split(KEY)).contains(key) + ).map(Map.Entry::getValue).collect(Collectors.toList()); } /** - * 精确匹配 + * 根据 topic 获取 精确匹配key的集合数据 * @param topic - * @param key + * @param key1 + * @param key2 * @return */ - public ObjectNode findAccurateObjectNode(String topic, String key) { + public List findMapAccurate2Key(String topic, String key1, String key2) { ConcurrentHashMap valMap = thingMap.get(topic); if(MapUtils.isEmpty(valMap)){ - return null; - } - Optional first = valMap.entrySet().stream().filter(entry -> - Arrays.asList(entry.getKey().split(":")).contains(key) - ).map(Map.Entry::getValue).findFirst(); - return first.orElse(null); + return Collections.emptyList(); + } +// List collect = valMap.entrySet().stream().filter(entry -> +// Arrays.asList(entry.getKey().split(KEY)).contains(key1) && Arrays.asList(entry.getKey().split(KEY)).contains(key2) +// ).map(Map.Entry::getValue).collect(Collectors.toList()); +// if(CollectionUtils.isEmpty(collect)){ +// System.out.println(collect+">>>"+key1+"--------------------匹配不上了-------------------"+key2); +// return collect; +// }else{ +// System.out.println(key1+"--------------------匹配上了-------------------"+key2); +// return collect; +// } + return valMap.entrySet().stream().filter(entry -> + Arrays.asList(entry.getKey().split(KEY)).contains(key1) && Arrays.asList(entry.getKey().split(KEY)).contains(key2) + ).map(Map.Entry::getValue).collect(Collectors.toList()); } + /** + * 根据 topic 获取 精确匹配 key的集合数据 + * @param topic + * @param keys + * @return + */ + public List findMapAccurateKeys(String topic, String ... keys) { + ConcurrentHashMap valMap = thingMap.get(topic); + if(MapUtils.isEmpty(valMap)){ + return Collections.emptyList(); + } + Set keySet = new HashSet<>(Arrays.asList(keys)); + return valMap.entrySet().stream().filter(entry -> + { + Set entryKeySet = new HashSet<>(Arrays.asList(entry.getKey().split(KEY))); + //不包含返回 true,包含返回false + return !Collections.disjoint(keySet, entryKeySet); + }).map(Map.Entry::getValue).collect(Collectors.toList()); + } + /** + * 根据 topic 和 key 更新数据,不存在相同的key就会存入缓存中,存在就不覆盖 + * @param topic + * @param key 完整的key + * @param value + */ + public void updateAccurateKeyMap(String topic, String key,ObjectNode value) { + ConcurrentHashMap valMap = thingMap.get(topic); + if(MapUtils.isEmpty(valMap)){ + valMap = new ConcurrentHashMap<>(); + } + //直接利用key覆盖 + valMap.put(key,value); + thingMap.put(topic,valMap); + } + /** + * 精确更新:根据 topic 和 key 更新数据,不存在相同的key就会存入缓存中,存在就不覆盖 + * @param topic + * @param key 完整的key + * @param record + */ + public void updateAccurateKeyEntity(String topic, String key,T record) { + if(!Objects.isNull(record)){ + ObjectNode nodes = JsonConverter.convertToJsonObjectObjectNode(record); + updateAccurateKeyMap(topic,key,nodes); + } + } + /** + * 精确删除 + * @param topic + * @param key + */ public void deleteKeyMap(String topic, String key) { ConcurrentHashMap valMap = thingMap.get(topic); if(MapUtils.isEmpty(valMap)){ @@ -131,13 +165,6 @@ public final class ThingCache { valMap.remove(key); } - public void clearTopic(String topic) { - ConcurrentHashMap valMap = thingMap.get(topic); - if(MapUtils.isNotEmpty(valMap)){ - valMap.clear(); - } - } - public void deleteAllKeyMap(String topic, Collection key) { ConcurrentHashMap valMap = thingMap.get(topic); if(MapUtils.isEmpty(valMap)){ @@ -149,24 +176,58 @@ public final class ThingCache { }); } - public void updateKeyMap(String topic, String key,ObjectNode value) { + + /** + * 根据topic清除缓存:此方法慎用,甚至不要用 + * @param topic + */ + public void clearTopic(String topic) { ConcurrentHashMap valMap = thingMap.get(topic); - if(MapUtils.isEmpty(valMap)){ - valMap = new ConcurrentHashMap<>(); + if(MapUtils.isNotEmpty(valMap)){ + valMap.clear(); } - //直接利用key覆盖 - valMap.put(key,value); - thingMap.put(topic,valMap); } - public List findAllKeyMap(String topic, Collection key) { - ConcurrentHashMap valMap = thingMap.get(topic); - if(MapUtils.isEmpty(valMap)){ - return null; + //以下方法需要时候打开 +/* + public List getTopicMap(String topic, String key) { + ConcurrentHashMap map = thingMap.get(topic); + if (map == null || map.isEmpty()) { + return List.of(); } - return valMap.entrySet().stream().filter(entry -> - key.stream().anyMatch(k -> entry.getKey().contains(k)) - ).map(Map.Entry::getValue).collect(Collectors.toList()); + return map.entrySet().stream() + .filter(entry -> StringUtils.contains(entry.getKey(), key)) + .sorted(Map.Entry.comparingByKey()) + .map(Map.Entry::getValue) + .toList(); + } + + public List getTopicMap(String topic, List keys) { + ConcurrentHashMap map = thingMap.get(topic); + if (map == null || map.isEmpty()) { + return List.of(); + } + return map.entrySet().stream() + .filter(entry -> keys.stream().anyMatch(key-> StringUtils.contains(entry.getKey(), key))) + .sorted(Map.Entry.comparingByKey()) + .map(Map.Entry::getValue) + .toList(); + } + + public List getTopicMap(String topic, int size) { + Map map = thingMap.get(topic); + if (map == null || map.isEmpty() || size <= 0) { + return List.of(); + } + return map.entrySet().stream().sorted(Map.Entry.comparingByKey()).limit(size).map(Map.Entry::getValue).collect(Collectors.toList()); + } + + public Map getMap(String topic, int size) { + Map map = thingMap.get(topic); + if (map == null || map.isEmpty() || size <= 0) { + return Map.of(); + } + return map.entrySet().stream().sorted(Map.Entry.comparingByKey()).limit(size).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } public ObjectNode getKeyMap(String topic, String key) { @@ -179,7 +240,7 @@ public final class ThingCache { public int getTopicSize(String topic) { return thingMap.get(topic).size(); - } + }*/ public void printStats() { thingMap.forEach((topic, queue) -> { diff --git a/modules/thing/src/main/java/com/thing/thing/context/service/ThingManageContextService.java b/modules/thing/src/main/java/com/thing/thing/context/service/ThingManageContextService.java index 0a1d5bb..4de0914 100644 --- a/modules/thing/src/main/java/com/thing/thing/context/service/ThingManageContextService.java +++ b/modules/thing/src/main/java/com/thing/thing/context/service/ThingManageContextService.java @@ -24,13 +24,12 @@ public interface ThingManageContextService { Optional> findAllModel(String orderField, String order, String code, String token,String origin,String status,String realType,String gateway,Long startTime,Long endTime); - Optional> findModelByCodes(Collection codes); + Optional> findModelByCodes(Collection codes); Optional> findModelByGateway(String gateway); Optional findModelByGatewayAndToken(String gateway,String token); - void saveModelBatch(List models); /** 查询 Entity 接口 **/ @@ -111,17 +110,9 @@ public interface ThingManageContextService { /** 插入接口 **/ - void saveModel(List codes); void saveOneModel(IotThingModelEntity entity); - void saveAllModel(List entities); - - void saveEntity(List entities); - - -// void insertBatchModel(List entities); - void batchSaveOrUpdateEntity(List collect); diff --git a/modules/thing/src/main/java/com/thing/thing/context/service/impl/ThingManageContextServiceImpl.java b/modules/thing/src/main/java/com/thing/thing/context/service/impl/ThingManageContextServiceImpl.java index 32aafc2..edf506e 100644 --- a/modules/thing/src/main/java/com/thing/thing/context/service/impl/ThingManageContextServiceImpl.java +++ b/modules/thing/src/main/java/com/thing/thing/context/service/impl/ThingManageContextServiceImpl.java @@ -73,7 +73,7 @@ public class ThingManageContextServiceImpl implements ThingManageContextService } @Override - public Optional> findModelByCodes(Collection codes) { + public Optional> findModelByCodes(Collection codes) { return Optional.ofNullable(modelService.findByCodeIn(codes)); } @@ -87,12 +87,6 @@ public class ThingManageContextServiceImpl implements ThingManageContextService return modelService.findModelByGatewayAndToken(gateway,token); } - @Override - public void saveModelBatch(List models) { - List entities = ConvertUtils.sourceToTarget(models, IotThingModelEntity.class); - modelService.batchSaveOrUpdate(entities); - } - @Override public Optional findEntityById(Long id) { return Optional.ofNullable(entityService.findEntityById(id)); @@ -236,41 +230,17 @@ public class ThingManageContextServiceImpl implements ThingManageContextService return Optional.ofNullable(dictService.findDictByGroupNameAndCodes(groupName,code)); } - @Override - public void saveModel(List codes) { - List list = codes.stream().distinct().map(code -> new IotThingModelEntity() - .setCode(code) - .setToken(TokenGenerator.generateValue()) - .setGateway(GateWayStatus.NO_GATE_WAY.getValue()) - .setStatus(ThingStatus.NOT_CONNECTED.getCode()) - .setOrigin(QueueOriginType.MQTT_CLIENT.name()) - .setStatusTs(DateTimeUtils.getCurrentTime()) - ).toList(); - modelService.saveBatch(list); - } - @Override public void saveOneModel(IotThingModelEntity entity) { modelService.save(entity); } - @Override - public void saveAllModel(List entities) { - modelService.batchSaveOrUpdate(entities); - } - - @Override - public void saveEntity(List entities) { - entityService.saveBatch(entities); - } - @Override public void batchSaveOrUpdateEntity(List collect) { if (CollectionUtil.isEmpty(collect)) { return; } entityService.batchSaveOrUpdate(collect); - } @Override diff --git a/modules/thing/src/main/java/com/thing/thing/dictRelation/service/impl/IotThingDictRelationServiceImpl.java b/modules/thing/src/main/java/com/thing/thing/dictRelation/service/impl/IotThingDictRelationServiceImpl.java index c273b73..fa37f2a 100644 --- a/modules/thing/src/main/java/com/thing/thing/dictRelation/service/impl/IotThingDictRelationServiceImpl.java +++ b/modules/thing/src/main/java/com/thing/thing/dictRelation/service/impl/IotThingDictRelationServiceImpl.java @@ -320,8 +320,10 @@ public class IotThingDictRelationServiceImpl extends BaseServiceImpl cache.updateAccurateKeyEntity(CacheNameEnum.THING_DICT_RELATION, + entity.getTenantCode()+CacheInit.KEY+entity.getEntityCode()+CacheInit.KEY+entity.getCode()+CacheInit.KEY+entity.getId(),ConvertUtils.sourceToTarget(entity, IotThingDictRelationDTO.class))); } - cache.clearTopic(CacheNameEnum.THING_DICT_RELATION); } @Transactional(rollbackFor = Exception.class) @@ -365,16 +367,20 @@ public class IotThingDictRelationServiceImpl extends BaseServiceImpl cache.updateAccurateKeyEntity(CacheNameEnum.THING_DICT_RELATION, + entity.getTenantCode()+CacheInit.KEY+entity.getEntityCode()+CacheInit.KEY+entity.getCode()+CacheInit.KEY+entity.getId(),ConvertUtils.sourceToTarget(entity, IotThingDictRelationDTO.class))); + } - cache.clearTopic(CacheNameEnum.THING_DICT_RELATION); } @Transactional(rollbackFor = Exception.class) @Override public void update(IotThingDictRelationDTO dto) { Long id = dto.getId(); - IotThingDictRelationDTO dictRelationDTO = findById(id); - if (Objects.isNull(dictRelationDTO)) { + + IotThingDictRelationEntity dictRelationEntity = mapper.selectOneById(id); + if (Objects.isNull(dictRelationEntity)) { throw new SysException("当前指标不存在"); } String url = BizUtils.trimAll(dto.getUrl()); @@ -382,7 +388,7 @@ public class IotThingDictRelationServiceImpl extends BaseServiceImpl dictRelationEntities = mapper.selectListByQuery(in); mapper.deleteBatchByIds(Arrays.asList(ids)); - cache.clearTopic(CacheNameEnum.THING_DICT_RELATION); + //删除缓存 + dictRelationEntities.forEach(entity -> cache.deleteKeyMap(CacheNameEnum.THING_DICT_RELATION, + entity.getTenantCode()+CacheInit.KEY+entity.getEntityCode()+CacheInit.KEY+entity.getCode()+CacheInit.KEY+entity.getId())); } @Transactional(rollbackFor = Exception.class) @Override public void saveBatchDictRelation(Collection dto) { - mapper.insertBatch(ConvertUtils.sourceToTarget(dto, IotThingDictRelationEntity.class)); - cache.clearTopic(CacheNameEnum.THING_DICT_RELATION); + List dictRelationEntities = ConvertUtils.sourceToTarget(dto, IotThingDictRelationEntity.class); + mapper.insertBatch(dictRelationEntities); + //更新缓存 + dictRelationEntities.forEach(entity -> cache.updateAccurateKeyEntity(CacheNameEnum.THING_DICT_RELATION, + entity.getTenantCode()+CacheInit.KEY+entity.getEntityCode()+CacheInit.KEY+entity.getCode()+CacheInit.KEY+entity.getId(),ConvertUtils.sourceToTarget(entity, IotThingDictRelationDTO.class))); } @Transactional(rollbackFor = Exception.class) @@ -447,8 +464,9 @@ public class IotThingDictRelationServiceImpl extends BaseServiceImpl cache.updateAccurateKeyEntity(CacheNameEnum.THING_DICT_RELATION, + entity.getTenantCode()+CacheInit.KEY+entity.getEntityCode()+CacheInit.KEY+entity.getCode()+CacheInit.KEY+entity.getId(),ConvertUtils.sourceToTarget(entity, IotThingDictRelationDTO.class))); } - cache.clearTopic(CacheNameEnum.THING_DICT_RELATION); } @Override @@ -501,7 +519,6 @@ public class IotThingDictRelationServiceImpl extends BaseServiceImpl noexistCodes = list.stream().filter(e -> dictDTOS.stream().noneMatch(d -> StringUtils.equals(d.getCode(), e.getCode()))).toList(); - if (CollectionUtils.isNotEmpty(noexistCodes)) { Integer maxSort = dictService.findMaxSort(1); AtomicInteger sort = new AtomicInteger(maxSort); @@ -521,8 +538,10 @@ public class IotThingDictRelationServiceImpl extends BaseServiceImpl iotThingDictRelationEntities = ConvertUtils.sourceToTarget(list, IotThingDictRelationEntity.class); mapper.insertBatch(iotThingDictRelationEntities); + + iotThingDictRelationEntities.forEach(entity -> cache.updateAccurateKeyEntity(CacheNameEnum.THING_DICT_RELATION, + entity.getTenantCode()+CacheInit.KEY+entity.getEntityCode()+CacheInit.KEY+entity.getCode()+CacheInit.KEY+entity.getId(),ConvertUtils.sourceToTarget(entity, IotThingDictRelationDTO.class))); } - cache.clearTopic(CacheNameEnum.THING_DICT_RELATION); } @Transactional(rollbackFor = Exception.class) @@ -556,8 +575,14 @@ public class IotThingDictRelationServiceImpl extends BaseServiceImpl dictRelationEntities = mapper.selectListByQuery(in); + mapper.deleteByQuery(in); + dictRelationEntities.forEach(entity -> cache.deleteKeyMap(CacheNameEnum.THING_DICT_RELATION, + entity.getTenantCode()+CacheInit.KEY+entity.getEntityCode()+CacheInit.KEY+entity.getCode()+CacheInit.KEY+entity.getId())); mapper.insertBatch(insertList); + insertList.forEach(entity -> cache.updateAccurateKeyEntity(CacheNameEnum.THING_DICT_RELATION, + entity.getTenantCode()+CacheInit.KEY+entity.getEntityCode()+CacheInit.KEY+entity.getCode()+CacheInit.KEY+entity.getId(),ConvertUtils.sourceToTarget(entity, IotThingDictRelationDTO.class))); }else{ List relationDTOList = findAllByEntityIdsAndCodes(entityIds, null); if(CollectionUtils.isNotEmpty(relationDTOList)){ @@ -570,9 +595,10 @@ public class IotThingDictRelationServiceImpl extends BaseServiceImpl cache.updateAccurateKeyEntity(CacheNameEnum.THING_DICT_RELATION, + entity.getTenantCode()+CacheInit.KEY+entity.getEntityCode()+CacheInit.KEY+entity.getCode()+CacheInit.KEY+entity.getId(),ConvertUtils.sourceToTarget(entity, IotThingDictRelationDTO.class))); } } - cache.clearTopic(CacheNameEnum.THING_DICT_RELATION); } diff --git a/modules/thing/src/main/java/com/thing/thing/entity/service/impl/IotThingEntityServiceImpl.java b/modules/thing/src/main/java/com/thing/thing/entity/service/impl/IotThingEntityServiceImpl.java index c8349f4..1293959 100644 --- a/modules/thing/src/main/java/com/thing/thing/entity/service/impl/IotThingEntityServiceImpl.java +++ b/modules/thing/src/main/java/com/thing/thing/entity/service/impl/IotThingEntityServiceImpl.java @@ -46,6 +46,7 @@ import com.thing.thing.entity.param.IotThingStatusDTO; import com.thing.thing.entity.service.IotThingEntityService; import com.thing.thing.group.entity.IotGroupRelationEntity; import com.thing.thing.group.service.IotGroupRelationService; +import com.thing.thing.model.dto.IotThingModelDTO; import com.thing.thing.model.dto.ModelDetailDTO; import com.thing.thing.model.entity.IotThingModelEntity; import com.thing.thing.model.service.IotThingModelService; @@ -101,7 +102,7 @@ public class IotThingEntityServiceImpl extends BaseServiceImpl thingList = cache.getTopicMap(CacheNameEnum.THING_ENTITY); + List thingList = thingCache.getTopicMap(CacheNameEnum.THING_ENTITY); if(CollectionUtils.isEmpty(thingList)){ List iotThingViewDTOS = mapper.selectListByQueryAs(getWrapper(orderField,order, null, null,null,null, null, null, null, null) @@ -276,7 +277,7 @@ public class IotThingEntityServiceImpl extends BaseServiceImpl iotThingEntities = mapper.selectListByQuery(in); mapper.deleteBatchByIds(Arrays.asList(ids)); - cache.clearTopic(CacheNameEnum.THING_ENTITY); + //删除物实体缓存 + iotThingEntities.forEach(entity -> thingCache.deleteKeyMap(CacheNameEnum.THING_ENTITY, + entity.getTenantCode()+CacheInit.KEY+entity.getCode()+CacheInit.KEY+entity.getId())); } @Override @@ -570,8 +582,9 @@ public class IotThingEntityServiceImpl extends BaseServiceImpl e.setEnableStatus(dto.getEnableStatus())); updateBatch(entities); -// entities.forEach(this::updateEntityCache); - cache.clearTopic(CacheNameEnum.THING_ENTITY); + entities.forEach(entity -> thingCache.updateAccurateKeyEntity(CacheNameEnum.THING_ENTITY, + entity.getTenantCode()+CacheInit.KEY+entity.getCode()+CacheInit.KEY+entity.getId(),convertIotThingViewDTO(entity, false))); + } @Override @@ -601,8 +614,9 @@ public class IotThingEntityServiceImpl extends BaseServiceImpl thingCache.updateAccurateKeyEntity(CacheNameEnum.THING_ENTITY, + entity.getTenantCode()+CacheInit.KEY+entity.getCode()+CacheInit.KEY+entity.getId(),convertIotThingViewDTO(entity, false))); List modelEntities = sheetData.stream().map(data -> new IotThingModelEntity() .setCode(data.getEntityCode()) .setStatus(ThingStatus.NOT_CONNECTED.getCode()) @@ -693,12 +710,11 @@ public class IotThingEntityServiceImpl extends BaseServiceImpl thingCache.updateAccurateKeyEntity(CacheNameEnum.THING_MODEL, + entity.getCode()+CacheInit.KEY+entity.getId(),ConvertUtils.sourceToTarget(entity, IotThingModelDTO.class))); } - cache.clearTopic(CacheNameEnum.THING_MODEL); - cache.clearTopic(CacheNameEnum.THING_ENTITY); - appEventPublisher.publishEvent(new ThingRelationDetailUpdateEvent(this, list)); - } } @@ -802,15 +818,21 @@ public class IotThingEntityServiceImpl extends BaseServiceImpl collect) { - collect.forEach(item -> mapper.insertOrUpdateSelective(item)); - cache.clearTopic(CacheNameEnum.THING_ENTITY); + collect.forEach(thingEntity -> { + mapper.insertOrUpdateSelective(thingEntity); + thingCache.updateAccurateKeyEntity(CacheNameEnum.THING_ENTITY, + thingEntity.getTenantCode()+CacheInit.KEY+thingEntity.getCode()+CacheInit.KEY+thingEntity.getId(),convertIotThingViewDTO(thingEntity, false)); + }); } @Transactional(rollbackFor = Exception.class) @Override public void saveBatchEntity(List entities) { mapper.insertBatch(entities); - cache.clearTopic(CacheNameEnum.THING_ENTITY); + entities.forEach(thingEntity -> + thingCache.updateAccurateKeyEntity(CacheNameEnum.THING_ENTITY, + thingEntity.getTenantCode()+CacheInit.KEY+thingEntity.getCode()+CacheInit.KEY+thingEntity.getId(), convertIotThingViewDTO(thingEntity, false)) + ); } @Override @@ -990,7 +1012,8 @@ public class IotThingEntityServiceImpl extends BaseServiceImpl list) { list.forEach(res -> { - List keyMap = cache.findKeyMap(CacheNameEnum.THING_MODEL, res.get(CacheNameEnum.EntityField.THING_ENTITY_CODE.getField()).asText()); + //根据设备编码精确查询设备模型 + List keyMap = thingCache.findMapAccurateKey(CacheNameEnum.THING_MODEL, res.get(CacheNameEnum.EntityField.THING_ENTITY_CODE.getField()).asText()); if(CollectionUtils.isNotEmpty(keyMap)){ res.put("status",keyMap.get(0).get(CacheNameEnum.ModelField.THING_MODEL_STATUS.getField()).asText()); res.put("statusTs",keyMap.get(0).get(CacheNameEnum.ModelField.THING_MODEL_STATUS_TS.getField()).asText()); @@ -1012,4 +1035,52 @@ public class IotThingEntityServiceImpl extends BaseServiceImpl nodeList = thingCache.findMapAccurateKey(CacheNameEnum.THING_MODEL, entity.getCode()); + ObjectNode modelMap = nodeList.get(0); + return new IotThingViewDTO() + .setLat(entity.getLat()) + .setLon(entity.getLon()) + .setTags(entity.getTags()) + .setDeptIds(entity.getDeptIds()) + .setOrigin(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_ORIGIN.getField()).asText()) + .setTemplateMark(entity.getTemplateMark()) + .setRealType(entity.getRealType()) + .setImg(entity.getImg()) + .setRemark(entity.getRemark()) + .setEnableStatus(entity.getEnableStatus()) + .setStatusTs(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_STATUS_TS.getField()).asLong()) + .setStatus(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_STATUS.getField()).asText()) + .setTenantCode(entity.getTenantCode()) + .setCompanyId(entity.getTenantCode()) + .setDeptId(entity.getTenantCode()) + .setEntityType(entity.getType()) + .setEntityName(entity.getName()) + .setEntityCode(entity.getCode()) + .setEntityId(entity.getId()) + .setModelId(modelMap.get(CacheNameEnum.ModelField.THING_MODEL_ID.getField()).asLong()) + .setCreateDate(entity.getCreateDate()); + } + } + } diff --git a/modules/thing/src/main/java/com/thing/thing/model/dto/IotThingModelDTO.java b/modules/thing/src/main/java/com/thing/thing/model/dto/IotThingModelDTO.java index 701bbfd..bc39f95 100644 --- a/modules/thing/src/main/java/com/thing/thing/model/dto/IotThingModelDTO.java +++ b/modules/thing/src/main/java/com/thing/thing/model/dto/IotThingModelDTO.java @@ -45,6 +45,8 @@ public class IotThingModelDTO implements Serializable { @Schema(description = "创建时间") @JsonSerialize(using = ToStringSerializer.class) private Long createDate; + @JsonSerialize(using = ToStringSerializer.class) + private Long creator; @Schema(description = "租户内物存在类型,0虚拟 1真实") private String realType; diff --git a/modules/thing/src/main/java/com/thing/thing/model/param/DistributeModelParam.java b/modules/thing/src/main/java/com/thing/thing/model/param/DistributeModelParam.java index 31151af..cc65e85 100644 --- a/modules/thing/src/main/java/com/thing/thing/model/param/DistributeModelParam.java +++ b/modules/thing/src/main/java/com/thing/thing/model/param/DistributeModelParam.java @@ -1,9 +1,7 @@ package com.thing.thing.model.param; -import com.thing.thing.model.dto.IotThingModelDTO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import lombok.EqualsAndHashCode; import java.io.Serial; import java.io.Serializable; diff --git a/modules/thing/src/main/java/com/thing/thing/model/service/IotThingModelService.java b/modules/thing/src/main/java/com/thing/thing/model/service/IotThingModelService.java index 15e30e3..5186fda 100644 --- a/modules/thing/src/main/java/com/thing/thing/model/service/IotThingModelService.java +++ b/modules/thing/src/main/java/com/thing/thing/model/service/IotThingModelService.java @@ -33,7 +33,7 @@ public interface IotThingModelService extends IBaseService Optional findModelByGatewayAndToken(String gateway, String token); - List findByCodeIn(Collection codeList); + List findByCodeIn(Collection codeList); List findAllOrigin(); diff --git a/modules/thing/src/main/java/com/thing/thing/model/service/impl/IotThingModelServiceImpl.java b/modules/thing/src/main/java/com/thing/thing/model/service/impl/IotThingModelServiceImpl.java index 93da625..5d9acb1 100644 --- a/modules/thing/src/main/java/com/thing/thing/model/service/impl/IotThingModelServiceImpl.java +++ b/modules/thing/src/main/java/com/thing/thing/model/service/impl/IotThingModelServiceImpl.java @@ -210,13 +210,8 @@ public class IotThingModelServiceImpl extends BaseServiceImpl findByCodeIn(Collection codeList) { - List modelList = cache.findAllKeyMap(CacheNameEnum.THING_MODEL, codeList); - if (CollectionUtils.isEmpty(modelList)) { - List modelDTOList = mapper.selectListByQueryAs(QueryWrapper.create().in(IotThingModelEntity::getCode, codeList), IotThingModelDTO.class); - return JsonConverter.convertToJsonObjectListObjectNode(modelDTOList); - } - return modelList; + public List findByCodeIn(Collection codeList) { + return mapper.selectListByQueryAs(QueryWrapper.create().in(IotThingModelEntity::getCode, codeList), IotThingModelDTO.class); } @Override @@ -307,18 +302,19 @@ public class IotThingModelServiceImpl extends BaseServiceImpl entitiesList = shareThingsToTenantCode(Collections.singletonList(code), dto.getTenantCodes()); Optional optional = findByCode(code); if (optional.isEmpty()) { - IotThingModelEntity modelEntity = buildIotThingModelEntity(code, dto.getRemark(), (long) CollectionUtils.size(entitiesList), null, dto.getGateway(),dto.getRealType()); + IotThingModelEntity modelEntity = buildIotThingModelEntity(code, dto.getRemark(), null, null, dto.getGateway(),dto.getRealType()); mapper.insert(modelEntity); + //更新物模型的缓存 + cache.updateAccurateKeyEntity(CacheNameEnum.THING_MODEL, + modelEntity.getCode()+CacheInit.KEY+modelEntity.getId(),ConvertUtils.sourceToTarget(modelEntity, ModelDetailDTO.class)); + //分配属性信息 + shareThingsToTenantCode(Collections.singletonList(code), dto.getTenantCodes()); + updateModelAuthNumByCodes(Collections.singletonList(code)); } else { updateModelAuthNumByCodes(Collections.singletonList(code)); } - //更新物实体的缓存 - cache.clearTopic(CacheNameEnum.THING_MODEL); - cache.clearTopic(CacheNameEnum.THING_ENTITY); return true; } @@ -336,9 +332,9 @@ public class IotThingModelServiceImpl extends BaseServiceImpl entityDTOS = thingEntityService.findEntityAllByCode(Collections.singleton(entity.getCode()), null, true); entity.setAuthNum((long) CollectionUtils.size(entityDTOS)); mapper.insertOrUpdateSelective(entity); + //更新缓存 + cache.updateAccurateKeyEntity(CacheNameEnum.THING_MODEL, + entity.getCode()+CacheInit.KEY+entity.getId(),ConvertUtils.sourceToTarget(entity, ModelDetailDTO.class)); } ); - cache.clearTopic(CacheNameEnum.THING_MODEL); + } @Transactional(rollbackFor = Exception.class) @Override public void batchSaveOrUpdate(List modelEntities) { - modelEntities.forEach(model -> mapper.insertOrUpdate(model)); - cache.clearTopic(CacheNameEnum.THING_MODEL); + modelEntities.forEach(model -> { + mapper.insertOrUpdate(model); + cache.updateAccurateKeyEntity(CacheNameEnum.THING_MODEL, + model.getCode()+CacheInit.KEY+model.getId(),ConvertUtils.sourceToTarget(model, ModelDetailDTO.class)); + }); } @Override @@ -436,7 +435,7 @@ public class IotThingModelServiceImpl extends BaseServiceImpl(); } - @GetMapping("{id}/{toSort}") + @GetMapping("{id}/{toId}") @Operation(summary="拖拽修改顺序") @Parameters({ @Parameter(name = "id", description = "当前拖拽的关系id", required = true) , @Parameter(name = "toId", description = "拖拽目标的关系id", required = true) , @Parameter(name = "toSort", description = "拖拽目标位置", required = true) }) - public Result updateSort(@PathVariable("id") Long id, @PathVariable("toSort") Long toSort){ - service.updateSort(id, toSort); + public Result updateSort(@PathVariable("id") Long id, @PathVariable("toId") Long toId){ + service.updateSort(id, toId); + return new Result<>(); + } + + @GetMapping("updateSiblingSort/{id}/{sort}") + @Operation(summary="拖拽修改顺序") + @Parameters({ + @Parameter(name = "id", description = "当前拖拽的关系id", required = true) , + @Parameter(name = "toId", description = "拖拽目标的关系id", required = true) , + @Parameter(name = "toSort", description = "拖拽目标位置", required = true) + }) + public Result updateSiblingSort(@PathVariable("id") Long id, @PathVariable("sort") Long sort){ + service.updateSiblingSort(id, sort); return new Result<>(); } diff --git a/modules/thing/src/main/java/com/thing/thing/relation/detail/service/IotThingRelationDetailService.java b/modules/thing/src/main/java/com/thing/thing/relation/detail/service/IotThingRelationDetailService.java index a6a5047..fbf61bc 100644 --- a/modules/thing/src/main/java/com/thing/thing/relation/detail/service/IotThingRelationDetailService.java +++ b/modules/thing/src/main/java/com/thing/thing/relation/detail/service/IotThingRelationDetailService.java @@ -25,6 +25,8 @@ public interface IotThingRelationDetailService extends IBaseService findByFromIdAndToId(Long fromId,Long toId); List findByRootId(Long rootId); @@ -43,7 +45,9 @@ public interface IotThingRelationDetailService extends IBaseService collect = relationDetailList.stream().sorted(Comparator.comparingLong(node -> node.get(CacheNameEnum.RelationDetailField.THING_RELATION_DETAIL_SORT.getField()).asLong())).collect(Collectors.toList()); + //分页 - List resPageList = PageUtils.startPage(relationDetailList, page, limit); + List resPageList = PageUtils.startPage(collect, page, limit); /* //找到第一节点 :先保留这个注释代码,可能会用到 List resList = detailList.stream() .filter(d -> StringUtils.equals( @@ -187,7 +190,15 @@ public class IotThingRelationDetailServiceImpl extends BaseServiceImpl buildDetails(IotThingRelationDetailParamDTO dto, List subRelationList) { @@ -306,12 +317,23 @@ public class IotThingRelationDetailServiceImpl extends BaseServiceImpl iotThingRelationDetailEntities = mapper.selectListByQuery(QueryWrapper.create().eq(IotThingRelationDetailEntity::getRootId, request.getRootId())); if (CollectionUtils.isNotEmpty(iotThingRelationDetailEntities)) { //删除全部关系 mapper.deleteByQuery(QueryWrapper.create().eq(IotThingRelationDetailEntity::getRootId, request.getRootId())); + iotThingRelationDetailEntities.forEach(entity -> cache.deleteKeyMap(CacheNameEnum.THING_DETAIL_RELATION, + entity.getRootId()+CacheInit.KEY+entity.getId()+CacheInit.KEY+entity.getRootThingId())); } //重构关系入库 List list = detailList.stream().flatMap(item -> { @@ -333,7 +355,8 @@ public class IotThingRelationDetailServiceImpl extends BaseServiceImpl cache.updateAccurateKeyEntity(CacheNameEnum.THING_DETAIL_RELATION, + entity.getRootId()+CacheInit.KEY+entity.getId()+CacheInit.KEY+entity.getRootThingId(),ConvertUtils.sourceToTarget(entity, IotThingRelationDetailDTO.class))); } @Transactional(rollbackFor = Exception.class) @@ -349,9 +372,9 @@ public class IotThingRelationDetailServiceImpl extends BaseServiceImpl iotThingRelationDetailEntities = mapper.selectListByQuery(QueryWrapper.create().eq(IotThingRelationDetailEntity::getRootId, dto.getRootId())); @@ -395,27 +419,23 @@ public class IotThingRelationDetailServiceImpl extends BaseServiceImpl targetChildIds = list.stream().map(IotThingRelationDetailEntity::getId).toList(); - //找出不包源节点 , 目标节点顺序的节点 ,并且顺序小于目标节点顺序的节点 List xlist = iotThingRelationDetailEntities.stream().filter(d -> !sourceChildIds.contains(d.getId()) && !targetChildIds.contains(d.getId()) && list.get(list.size()-1).getSort() < d.getSort()).toList(); - resultList.addAll(xlist); - //更新排序 AtomicLong sort = new AtomicLong(0); resultList.forEach(item -> { item.setSort(sort.incrementAndGet()); mapper.updateByQuery(item, QueryWrapper.create().eq(IotThingRelationDetailEntity::getId, item.getId())); + cache.updateAccurateKeyEntity(CacheNameEnum.THING_DETAIL_RELATION, + item.getRootId()+CacheInit.KEY+item.getId()+CacheInit.KEY+item.getRootThingId(),ConvertUtils.sourceToTarget(item, IotThingRelationDetailDTO.class)); } ); } } - //更新缓存 - cache.clearTopic(CacheNameEnum.THING_DETAIL_RELATION); } private void findAllChild(List allRelation, @@ -432,51 +452,134 @@ public class IotThingRelationDetailServiceImpl extends BaseServiceImpl relationDetailEntities = mapper.selectListByQuery(eq); mapper.deleteByQuery(QueryWrapper.create().eq(IotThingRelationDetailEntity::getRootId, rootId)); - cache.clearTopic(CacheNameEnum.THING_DETAIL_RELATION); + relationDetailEntities.forEach(detailEntity -> cache.deleteKeyMap(CacheNameEnum.THING_DETAIL_RELATION, + detailEntity.getRootId()+CacheInit.KEY+detailEntity.getId()+CacheInit.KEY+detailEntity.getRootThingId())); } @Override public void deleteById(Long id) { + QueryWrapper eq = QueryWrapper.create().eq(IotThingRelationDetailEntity::getId, id); + IotThingRelationDetailEntity detailEntity = mapper.selectOneByQuery(eq); mapper.deleteByQuery(QueryWrapper.create().eq(IotThingRelationDetailEntity::getId, id)); - cache.clearTopic(CacheNameEnum.THING_DETAIL_RELATION); + cache.deleteKeyMap(CacheNameEnum.THING_DETAIL_RELATION, + detailEntity.getRootId()+CacheInit.KEY+detailEntity.getId()+CacheInit.KEY+detailEntity.getRootThingId()); } @Override - public void updateSort(Long id, Long toSort) { - //拖拽关系 + public void updateSort(Long id, Long toId) { + //d拖拽关系 IotThingRelationDetailEntity sourceEntity = mapper.selectOneById(id); if (Objects.isNull(sourceEntity)) { throw new SysException("当前拖拽的关系不存在,请重新选择"); } - //查询所有同级别的关系记录 - List sourceList = mapper.selectListByQuery(new QueryWrapper() - .eq(IotThingRelationDetailEntity::getRootId, sourceEntity.getRootId()) - .eq(IotThingRelationDetailEntity::getRootThingId, sourceEntity.getRootThingId()) - .eq(IotThingRelationDetailEntity::getFromId, sourceEntity.getFromId()) - .ne(IotThingRelationDetailEntity::getId, sourceEntity.getId()) - .orderBy(IotThingRelationDetailEntity::getSort, true)); + //若id和toId相等,则放置在所有关系的第一层,即顶级关系 List resultList = Lists.newArrayList(); - //向上:这里的条件判断是利用list的元素顺序重新给整个节点赋sort值 - if (sourceEntity.getSort() > toSort) { - List upList = sourceList.stream().filter(item -> item.getSort() < toSort).toList(); - resultList.addAll(upList); - sourceEntity.setSort(toSort); - resultList.add(sourceEntity); - List downList = sourceList.stream().filter(item -> item.getSort() >= toSort).toList(); - resultList.addAll(downList); - } else { - List upList = sourceList.stream().filter(item -> item.getSort() <= toSort).toList(); - resultList.addAll(upList); - sourceEntity.setSort(toSort); - resultList.add(sourceEntity); - List downList = sourceList.stream().filter(item -> item.getSort() > toSort).toList(); - resultList.addAll(downList); + List resultChildList = Lists.newArrayList(); + if(Objects.equals(id,toId)){ + IotThingRelationRootDTO relationRootDTO = relationRootsService.findById(sourceEntity.getRootId()); + sourceEntity.setFromName(relationRootDTO.getName()); + sourceEntity.setFromCode(null); + sourceEntity.setFromId(sourceEntity.getRootId()); + resultChildList.add(sourceEntity); + //查询当前节点的所有子节点 + findAllChildNodesByToId(Lists.newArrayList(id),sourceEntity.getRootId(),sourceEntity.getRootThingId(),resultChildList); + //排序 + List list = resultChildList.stream().sorted(comparing(IotThingRelationDetailEntity::getSort)).toList(); + resultList.addAll(list); + + List allChildIds = resultChildList.stream().map(IotThingRelationDetailEntity::getId).toList(); + //查询所有其他的物关系记录 + List otherList = mapper.selectListByQuery(new QueryWrapper() + .eq(IotThingRelationDetailEntity::getRootId, sourceEntity.getRootId()) + .eq(IotThingRelationDetailEntity::getRootThingId, sourceEntity.getRootThingId()) + .notIn(IotThingRelationDetailEntity::getId, allChildIds) + .orderBy(IotThingRelationDetailEntity::getSort, true)); + resultList.addAll(otherList); + }else { + //查询目标节点 + IotThingRelationDetailEntity targetEntity = mapper.selectOneById(toId); + if (Objects.isNull(targetEntity)) { + throw new SysException("当前拖拽的目标节点关系不存在,请重新选择"); + } + //查询当前拖拽节点的所有子节点 + + sourceEntity.setFromId(targetEntity.getToId()); + sourceEntity.setFromCode(targetEntity.getToCode()); + sourceEntity.setFromName(targetEntity.getFromName()); + + resultChildList.add(sourceEntity); + findAllChildNodesByToId(Lists.newArrayList(id),sourceEntity.getRootId(),sourceEntity.getRootThingId(),resultChildList); + + //查询目标节点的子节点 + List targetChildList = Lists.newArrayList(); + findAllChildNodesByToId(Lists.newArrayList(id),sourceEntity.getRootId(),sourceEntity.getRootThingId(),targetChildList); + + //查询目标节点的所有兄弟节点 + + List allChildIds = resultChildList.stream().map(IotThingRelationDetailEntity::getId).toList(); + //查询所有其他的物关系记录 + List otherList = mapper.selectListByQuery(new QueryWrapper() + .eq(IotThingRelationDetailEntity::getRootId, sourceEntity.getRootId()) + .eq(IotThingRelationDetailEntity::getRootThingId, sourceEntity.getRootThingId()) + .notIn(IotThingRelationDetailEntity::getId, allChildIds) + .le(IotThingRelationDetailEntity::getSort, targetEntity.getSort()) + .orderBy(IotThingRelationDetailEntity::getSort, true)); + + resultChildList.addAll(otherList); + List list = resultChildList.stream().sorted(comparing(IotThingRelationDetailEntity::getSort)).toList(); + resultChildList.addAll(list); + + List otherList1 = mapper.selectListByQuery(new QueryWrapper() + .eq(IotThingRelationDetailEntity::getRootId, sourceEntity.getRootId()) + .eq(IotThingRelationDetailEntity::getRootThingId, sourceEntity.getRootThingId()) + .notIn(IotThingRelationDetailEntity::getId, allChildIds) + .gt(IotThingRelationDetailEntity::getSort, targetEntity.getSort()) + .orderBy(IotThingRelationDetailEntity::getSort, true)); + resultChildList.addAll(otherList1); } AtomicLong sort = new AtomicLong(1); resultList.forEach(item -> item.setSort(sort.getAndIncrement())); this.updateBatch(resultList); - cache.clearTopic(CacheNameEnum.THING_DETAIL_RELATION); + //更新缓存 + resultList.forEach(s -> cache.updateAccurateKeyEntity(CacheNameEnum.THING_DETAIL_RELATION, + s.getRootId()+CacheInit.KEY+s.getId()+CacheInit.KEY+s.getRootThingId(),ConvertUtils.sourceToTarget(s, IotThingRelationDetailDTO.class))); + } + + @Override + public void updateSiblingSort(Long id, Long sort) { + IotThingRelationDetailEntity sourceEntity = mapper.selectOneById(id); + if (Objects.isNull(sourceEntity)) { + throw new SysException("当前拖拽的关系不存在,请重新选择"); + } + List reslutList = Lists.newArrayList(); + List otherList = mapper.selectListByQuery(new QueryWrapper() + .eq(IotThingRelationDetailEntity::getRootId, sourceEntity.getRootId()) + .eq(IotThingRelationDetailEntity::getRootThingId, sourceEntity.getRootThingId()) + .notIn(IotThingRelationDetailEntity::getId, sourceEntity.getId()) + .lt(IotThingRelationDetailEntity::getSort, sort) + .orderBy(IotThingRelationDetailEntity::getSort, true)); + + reslutList.addAll(otherList); + + sourceEntity.setSort(sort); + reslutList.add(sourceEntity); + List otherList1 = mapper.selectListByQuery(new QueryWrapper() + .eq(IotThingRelationDetailEntity::getRootId, sourceEntity.getRootId()) + .eq(IotThingRelationDetailEntity::getRootThingId, sourceEntity.getRootThingId()) + .notIn(IotThingRelationDetailEntity::getId, sourceEntity.getId()) + .ge(IotThingRelationDetailEntity::getSort, sort) + .orderBy(IotThingRelationDetailEntity::getSort, true)); + reslutList.addAll(otherList1); + + AtomicLong sort1 = new AtomicLong(1); + reslutList.forEach(item -> item.setSort(sort1.getAndIncrement())); + this.updateBatch(reslutList); + //更新缓存 + reslutList.forEach(s -> cache.updateAccurateKeyEntity(CacheNameEnum.THING_DETAIL_RELATION, + s.getRootId()+CacheInit.KEY+s.getId()+CacheInit.KEY+s.getRootThingId(),ConvertUtils.sourceToTarget(s, IotThingRelationDetailDTO.class))); } @Override @@ -497,14 +600,33 @@ public class IotThingRelationDetailServiceImpl extends BaseServiceImpl otherRelationList = mapper.selectListByQuery(queryWrapper); mapper.deleteBatchByIds(Arrays.asList(ids)); + //更新缓存 + iotThingRelationDetailEntities.forEach(entity -> cache.deleteKeyMap(CacheNameEnum.THING_DETAIL_RELATION, + entity.getRootId()+CacheInit.KEY+entity.getId()+CacheInit.KEY+entity.getRootThingId())); //更新序号 AtomicLong sort = new AtomicLong(1); otherRelationList.forEach(s -> { s.setSort(sort.getAndIncrement()); mapper.insertOrUpdateSelective(s); + //更新缓存 + cache.updateAccurateKeyEntity(CacheNameEnum.THING_DETAIL_RELATION, + s.getRootId()+CacheInit.KEY+s.getId()+CacheInit.KEY+s.getRootThingId(),ConvertUtils.sourceToTarget(s, IotThingRelationDetailDTO.class)); }); - //更新缓存 - cache.clearTopic(CacheNameEnum.THING_DETAIL_RELATION); + } + + + private void findAllChildNodesByToId(List toIds,Long rootId,Long rootThingId,List resultChildList){ + List childList = mapper.selectListByQuery(QueryWrapper.create() + .in(IotThingRelationDetailEntity::getFromId,toIds) + .in(IotThingRelationDetailEntity::getRootId,rootId) + .in(IotThingRelationDetailEntity::getRootThingId,rootThingId) + ); + if(CollectionUtils.isEmpty(childList)){ + return; + } + resultChildList.addAll(childList); + List childToId = childList.stream().map(IotThingRelationDetailEntity::getToId).toList(); + findAllChildNodesByToId(childToId,rootId,rootThingId,resultChildList); } @Override @@ -524,7 +646,7 @@ public class IotThingRelationDetailServiceImpl extends BaseServiceImpl findAllNotAddNodesById(Long id) { - List relationList = cache.findKeyMap(CacheNameEnum.THING_DETAIL_RELATION, id.toString()); + List relationList = cache.findMapAccurateKey(CacheNameEnum.THING_DETAIL_RELATION, id.toString()); if (CollectionUtils.isEmpty(relationList)) { throw new SysException("当前物关系不存在"); } @@ -886,8 +1008,8 @@ public class IotThingRelationDetailServiceImpl extends BaseServiceImpl entityNode = cache.findKeyMap(CacheNameEnum.THING_ENTITY, String.valueOf(UserContext.getRealTenantCode()) - + ":" + rootChildNode.get(CacheNameEnum.RelationDetailField.THING_RELATION_DETAIL_TO_CODE.getField()).asText()); + List entityNode = cache.findMapAccurateKeys(CacheNameEnum.THING_ENTITY, String.valueOf(UserContext.getRealTenantCode()) + ,rootChildNode.get(CacheNameEnum.RelationDetailField.THING_RELATION_DETAIL_TO_CODE.getField()).asText()); if (CollectionUtils.isNotEmpty(entityNode)) { rootChildNode.put(CacheNameEnum.RelationRootField.THING_RELATION_ROOT_ENTITY_TYPE.getField(), entityNode.get(0).get(CacheNameEnum.EntityField.THING_ENTITY_TYPE.getField()).asText()); } @@ -929,8 +1051,8 @@ public class IotThingRelationDetailServiceImpl extends BaseServiceImpl entityNode = cache.findKeyMap(CacheNameEnum.THING_ENTITY, String.valueOf(UserContext.getRealTenantCode()) - + ":" + rootChildNode.get(CacheNameEnum.RelationDetailField.THING_RELATION_DETAIL_TO_CODE.getField()).asText()); + List entityNode = cache.findMapAccurateKeys(CacheNameEnum.THING_ENTITY, String.valueOf(UserContext.getRealTenantCode()) + , rootChildNode.get(CacheNameEnum.RelationDetailField.THING_RELATION_DETAIL_TO_CODE.getField()).asText()); if (CollectionUtils.isNotEmpty(entityNode)) { rootChildNode.put(CacheNameEnum.RelationRootField.THING_RELATION_ROOT_ENTITY_TYPE.getField(), entityNode.get(0).get(CacheNameEnum.EntityField.THING_ENTITY_TYPE.getField()).asText()); } diff --git a/modules/thing/src/main/java/com/thing/thing/relation/root/service/impl/IotThingRelationRootServiceImpl.java b/modules/thing/src/main/java/com/thing/thing/relation/root/service/impl/IotThingRelationRootServiceImpl.java index 9ee35e2..64cb123 100644 --- a/modules/thing/src/main/java/com/thing/thing/relation/root/service/impl/IotThingRelationRootServiceImpl.java +++ b/modules/thing/src/main/java/com/thing/thing/relation/root/service/impl/IotThingRelationRootServiceImpl.java @@ -8,10 +8,7 @@ import com.thing.common.cache.constants.CacheNameEnum; import com.thing.common.core.constants.Constant; import com.thing.common.core.enumeration.ThingSortType; import com.thing.common.core.exception.SysException; -import com.thing.common.core.utils.BizUtils; -import com.thing.common.core.utils.CompareUtils; -import com.thing.common.core.utils.JacksonUtil; -import com.thing.common.core.utils.PageUtils; +import com.thing.common.core.utils.*; import com.thing.common.core.web.response.PageData; import com.thing.common.orm.service.impl.BaseServiceImpl; import com.thing.sys.oss.cloud.OSSFactory; @@ -155,19 +152,21 @@ public class IotThingRelationRootServiceImpl extends BaseServiceImpl rootEntities = mapper.selectListByQuery(queryWrapper); mapper.deleteBatchByIds(Arrays.asList(ids)); - cache.clearTopic(CacheNameEnum.THING_ROOT_RELATION); + rootEntities.forEach(rootEntity -> { + //更新缓存 + cache.deleteKeyMap(CacheNameEnum.THING_ROOT_RELATION, + rootEntity.getGroupName()+CacheInit.KEY+rootEntity.getName()+CacheInit.KEY+rootEntity.getId()); + }); } /** @@ -359,6 +378,10 @@ public class IotThingRelationRootServiceImpl extends BaseServiceImpl> buildParam(String name, String groupName,Long tenantCode){