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

This commit is contained in:
YunaiV 2024-12-26 12:57:56 +08:00
parent 09a26666ec
commit 7b64b7fc69
4 changed files with 21 additions and 15 deletions

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.List; import java.util.List;
@ -47,7 +48,8 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> {
} }
default IotDeviceDO selectByDeviceKey(String deviceKey) { default IotDeviceDO selectByDeviceKey(String deviceKey) {
return selectOne(IotDeviceDO::getDeviceKey, deviceKey); return selectOne(new LambdaQueryWrapper<IotDeviceDO>()
.apply("LOWER(device_key) = {0}", deviceKey.toLowerCase()));
} }
default List<IotDeviceDO> selectList(Integer deviceType) { default List<IotDeviceDO> selectList(Integer deviceType) {

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
/** /**
@ -23,7 +24,8 @@ public interface IotProductMapper extends BaseMapperX<IotProductDO> {
} }
default IotProductDO selectByProductKey(String productKey) { default IotProductDO selectByProductKey(String productKey) {
return selectOne(IotProductDO::getProductKey, productKey); return selectOne(new LambdaQueryWrapper<IotProductDO>()
.apply("LOWER(product_key) = {0}", productKey.toLowerCase()));
} }
} }

View File

@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceGroupDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceGroupDO;
@ -60,10 +61,11 @@ public class IotDeviceServiceImpl implements IotDeviceService {
throw exception(PRODUCT_NOT_EXISTS); throw exception(PRODUCT_NOT_EXISTS);
} }
// 1.2 校验设备标识是否唯一 // 1.2 校验设备标识是否唯一
// TODO 芋艿校验时需要跨租户唯一避免 TDEngine 无法处理并且要忽略大小写 TenantUtils.executeIgnore(() -> {
if (deviceMapper.selectByDeviceKey(createReqVO.getDeviceKey()) != null) { if (deviceMapper.selectByDeviceKey(createReqVO.getDeviceKey()) != null) {
throw exception(DEVICE_KEY_EXISTS); throw exception(PRODUCT_KEY_EXISTS);
} }
});
// 1.3 校验设备名称在同一产品下是否唯一 // 1.3 校验设备名称在同一产品下是否唯一
if (deviceMapper.selectByProductKeyAndDeviceName(product.getProductKey(), createReqVO.getDeviceKey()) != null) { if (deviceMapper.selectByProductKeyAndDeviceName(product.getProductKey(), createReqVO.getDeviceKey()) != null) {
throw exception(DEVICE_NAME_EXISTS); throw exception(DEVICE_NAME_EXISTS);

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.service.product;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
@ -9,7 +10,6 @@ import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper;
import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum;
import cn.iocoder.yudao.module.iot.service.device.IotDevicePropertyDataService; import cn.iocoder.yudao.module.iot.service.device.IotDevicePropertyDataService;
import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService; import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService;
import cn.iocoder.yudao.module.iot.service.thingmodel.IotProductThingModelService;
import com.baomidou.dynamic.datasource.annotation.DSTransactional; import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
@ -34,9 +34,6 @@ public class IotProductServiceImpl implements IotProductService {
@Resource @Resource
private IotProductMapper productMapper; private IotProductMapper productMapper;
@Resource
@Lazy // 延迟加载解决循环依赖
private IotProductThingModelService thingModelFunctionService;
@Resource @Resource
@Lazy // 延迟加载解决循环依赖 @Lazy // 延迟加载解决循环依赖
private IotThingModelMessageService thingModelMessageService; private IotThingModelMessageService thingModelMessageService;
@ -46,11 +43,14 @@ public class IotProductServiceImpl implements IotProductService {
@Override @Override
public Long createProduct(IotProductSaveReqVO createReqVO) { public Long createProduct(IotProductSaveReqVO createReqVO) {
// 1. 生成 ProductKey // 1. 校验 ProductKey
// TODO 芋艿校验时需要跨租户唯一避免 TDEngine 无法处理并且要忽略大小写 TenantUtils.executeIgnore(() -> {
if (productMapper.selectByProductKey(createReqVO.getProductKey()) != null) { // 为什么忽略租户避免多个租户之间productKey 重复导致 TDengine 设备属性表重复
throw exception(PRODUCT_KEY_EXISTS); if (productMapper.selectByProductKey(createReqVO.getProductKey()) != null) {
} throw exception(PRODUCT_KEY_EXISTS);
}
});
// 2. 插入 // 2. 插入
IotProductDO product = BeanUtils.toBean(createReqVO, IotProductDO.class) IotProductDO product = BeanUtils.toBean(createReqVO, IotProductDO.class)
.setStatus(IotProductStatusEnum.UNPUBLISHED.getStatus()); .setStatus(IotProductStatusEnum.UNPUBLISHED.getStatus());