Commit 7b64b7fc69ad38c4cd9bd0616e68059d0661579f

Authored by YunaiV
1 parent 09a26666

【功能优化】IoT:跨租户校验 ProductKey 和 DeviceKey,避免跨租户的 Tdengine 表冲突

yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/IotDeviceMapper.java
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
7 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO; 7 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO;
8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
  9 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
9 import org.apache.ibatis.annotations.Mapper; 10 import org.apache.ibatis.annotations.Mapper;
10 11
11 import java.util.List; 12 import java.util.List;
@@ -47,7 +48,8 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> { @@ -47,7 +48,8 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> {
47 } 48 }
48 49
49 default IotDeviceDO selectByDeviceKey(String deviceKey) { 50 default IotDeviceDO selectByDeviceKey(String deviceKey) {
50 - return selectOne(IotDeviceDO::getDeviceKey, deviceKey); 51 + return selectOne(new LambdaQueryWrapper<IotDeviceDO>()
  52 + .apply("LOWER(device_key) = {0}", deviceKey.toLowerCase()));
51 } 53 }
52 54
53 default List<IotDeviceDO> selectList(Integer deviceType) { 55 default List<IotDeviceDO> selectList(Integer deviceType) {
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; 6 import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO;
7 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; 7 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
  8 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
8 import org.apache.ibatis.annotations.Mapper; 9 import org.apache.ibatis.annotations.Mapper;
9 10
10 /** 11 /**
@@ -23,7 +24,8 @@ public interface IotProductMapper extends BaseMapperX&lt;IotProductDO&gt; { @@ -23,7 +24,8 @@ public interface IotProductMapper extends BaseMapperX&lt;IotProductDO&gt; {
23 } 24 }
24 25
25 default IotProductDO selectByProductKey(String productKey) { 26 default IotProductDO selectByProductKey(String productKey) {
26 - return selectOne(IotProductDO::getProductKey, productKey); 27 + return selectOne(new LambdaQueryWrapper<IotProductDO>()
  28 + .apply("LOWER(product_key) = {0}", productKey.toLowerCase()));
27 } 29 }
28 30
29 } 31 }
30 \ No newline at end of file 32 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java
@@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 9 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
10 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; 10 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
11 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 11 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
  12 +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
12 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; 13 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*;
13 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 14 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
14 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceGroupDO; 15 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceGroupDO;
@@ -60,10 +61,11 @@ public class IotDeviceServiceImpl implements IotDeviceService { @@ -60,10 +61,11 @@ public class IotDeviceServiceImpl implements IotDeviceService {
60 throw exception(PRODUCT_NOT_EXISTS); 61 throw exception(PRODUCT_NOT_EXISTS);
61 } 62 }
62 // 1.2 校验设备标识是否唯一 63 // 1.2 校验设备标识是否唯一
63 - // TODO 芋艿:校验时,需要跨租户唯一,避免 TDEngine 无法处理;并且要忽略大小写  
64 - if (deviceMapper.selectByDeviceKey(createReqVO.getDeviceKey()) != null) {  
65 - throw exception(DEVICE_KEY_EXISTS);  
66 - } 64 + TenantUtils.executeIgnore(() -> {
  65 + if (deviceMapper.selectByDeviceKey(createReqVO.getDeviceKey()) != null) {
  66 + throw exception(PRODUCT_KEY_EXISTS);
  67 + }
  68 + });
67 // 1.3 校验设备名称在同一产品下是否唯一 69 // 1.3 校验设备名称在同一产品下是否唯一
68 if (deviceMapper.selectByProductKeyAndDeviceName(product.getProductKey(), createReqVO.getDeviceKey()) != null) { 70 if (deviceMapper.selectByProductKeyAndDeviceName(product.getProductKey(), createReqVO.getDeviceKey()) != null) {
69 throw exception(DEVICE_NAME_EXISTS); 71 throw exception(DEVICE_NAME_EXISTS);
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.service.product; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.service.product;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  5 +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
5 import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; 6 import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO;
6 import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; 7 import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO;
7 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; 8 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
@@ -9,7 +10,6 @@ import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper; @@ -9,7 +10,6 @@ import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper;
9 import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; 10 import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum;
10 import cn.iocoder.yudao.module.iot.service.device.IotDevicePropertyDataService; 11 import cn.iocoder.yudao.module.iot.service.device.IotDevicePropertyDataService;
11 import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService; 12 import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService;
12 -import cn.iocoder.yudao.module.iot.service.thingmodel.IotProductThingModelService;  
13 import com.baomidou.dynamic.datasource.annotation.DSTransactional; 13 import com.baomidou.dynamic.datasource.annotation.DSTransactional;
14 import jakarta.annotation.Resource; 14 import jakarta.annotation.Resource;
15 import org.springframework.context.annotation.Lazy; 15 import org.springframework.context.annotation.Lazy;
@@ -35,9 +35,6 @@ public class IotProductServiceImpl implements IotProductService { @@ -35,9 +35,6 @@ public class IotProductServiceImpl implements IotProductService {
35 private IotProductMapper productMapper; 35 private IotProductMapper productMapper;
36 36
37 @Resource 37 @Resource
38 - @Lazy // 延迟加载,解决循环依赖  
39 - private IotProductThingModelService thingModelFunctionService;  
40 - @Resource  
41 @Lazy // 延迟加载,解决循环依赖 38 @Lazy // 延迟加载,解决循环依赖
42 private IotThingModelMessageService thingModelMessageService; 39 private IotThingModelMessageService thingModelMessageService;
43 @Resource 40 @Resource
@@ -46,11 +43,14 @@ public class IotProductServiceImpl implements IotProductService { @@ -46,11 +43,14 @@ public class IotProductServiceImpl implements IotProductService {
46 43
47 @Override 44 @Override
48 public Long createProduct(IotProductSaveReqVO createReqVO) { 45 public Long createProduct(IotProductSaveReqVO createReqVO) {
49 - // 1. 生成 ProductKey  
50 - // TODO 芋艿:校验时,需要跨租户唯一,避免 TDEngine 无法处理;并且要忽略大小写  
51 - if (productMapper.selectByProductKey(createReqVO.getProductKey()) != null) {  
52 - throw exception(PRODUCT_KEY_EXISTS);  
53 - } 46 + // 1. 校验 ProductKey
  47 + TenantUtils.executeIgnore(() -> {
  48 + // 为什么忽略租户?避免多个租户之间,productKey 重复,导致 TDengine 设备属性表重复
  49 + if (productMapper.selectByProductKey(createReqVO.getProductKey()) != null) {
  50 + throw exception(PRODUCT_KEY_EXISTS);
  51 + }
  52 + });
  53 +
54 // 2. 插入 54 // 2. 插入
55 IotProductDO product = BeanUtils.toBean(createReqVO, IotProductDO.class) 55 IotProductDO product = BeanUtils.toBean(createReqVO, IotProductDO.class)
56 .setStatus(IotProductStatusEnum.UNPUBLISHED.getStatus()); 56 .setStatus(IotProductStatusEnum.UNPUBLISHED.getStatus());