Commit 7b64b7fc69ad38c4cd9bd0616e68059d0661579f
1 parent
09a26666
【功能优化】IoT:跨租户校验 ProductKey 和 DeviceKey,避免跨租户的 Tdengine 表冲突
Showing
4 changed files
with
21 additions
and
15 deletions
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<IotProductDO> { | @@ -23,7 +24,8 @@ public interface IotProductMapper extends BaseMapperX<IotProductDO> { | ||
| 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()); |