mirror of
https://gitee.com/myxzgzs/boyue-vue-pro.git
synced 2025-08-08 16:32:46 +08:00
【优化功能】 优化 tdengine 操作数据库相关代码
This commit is contained in:
parent
d7b8cf547f
commit
e3dcea9cb3
@ -1,18 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class BaseEntity {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据库名称
|
|
||||||
*/
|
|
||||||
private String dataBaseName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超级表名称
|
|
||||||
*/
|
|
||||||
private String superTableName;
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备数据导出 excel DTO
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class DeviceDataExportExcelDto {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备标识
|
|
||||||
*/
|
|
||||||
private String deviceKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出形式 1 单个参数导出 2 全部参数导出
|
|
||||||
*/
|
|
||||||
private String exportType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出开始时间
|
|
||||||
*/
|
|
||||||
private String exportBeginTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出结束时间
|
|
||||||
*/
|
|
||||||
private String exportEndTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出参数,空则导出全部
|
|
||||||
*/
|
|
||||||
private String exportParameter;
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ClassDescription: 查询可视化所需入参对象
|
|
||||||
* @ClassName: SelectDto
|
|
||||||
* @Author: andyz
|
|
||||||
* @Date: 2022-07-29 14:12:26
|
|
||||||
* @Version 1.0
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class DeviceDataVo {
|
|
||||||
|
|
||||||
|
|
||||||
private String deviceId;
|
|
||||||
|
|
||||||
private Long lastTime;
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class Fields {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字段名称
|
|
||||||
*/
|
|
||||||
private String fieldName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字段值
|
|
||||||
*/
|
|
||||||
private Object fieldValue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字段数据类型
|
|
||||||
*/
|
|
||||||
// private DataTypeEnum dataType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字段字节大小
|
|
||||||
*/
|
|
||||||
private Integer size;
|
|
||||||
|
|
||||||
public Fields() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Fields(String fieldName, String dataType, Integer size) {
|
|
||||||
// this.fieldName = fieldName;
|
|
||||||
// //根据规则匹配字段数据类型
|
|
||||||
// switch (dataType.toLowerCase()) {
|
|
||||||
// case ("json"):
|
|
||||||
// this.dataType = DataTypeEnum.JSON;
|
|
||||||
// this.size = size;
|
|
||||||
// break;
|
|
||||||
// case ("string"):
|
|
||||||
// this.dataType = DataTypeEnum.NCHAR;
|
|
||||||
// this.size = size;
|
|
||||||
// break;
|
|
||||||
// case ("binary"):
|
|
||||||
// this.dataType = DataTypeEnum.BINARY;
|
|
||||||
// this.size = size;
|
|
||||||
// break;
|
|
||||||
// case ("int"):
|
|
||||||
// this.dataType = DataTypeEnum.INT;
|
|
||||||
// break;
|
|
||||||
// case ("bool"):
|
|
||||||
// this.dataType = DataTypeEnum.BOOL;
|
|
||||||
// break;
|
|
||||||
// case ("decimal"):
|
|
||||||
// this.dataType = DataTypeEnum.DOUBLE;
|
|
||||||
// break;
|
|
||||||
// case ("timestamp"):
|
|
||||||
// if ("eventTime".equals(fieldName)) {
|
|
||||||
// this.fieldName = "eventTime";
|
|
||||||
// }
|
|
||||||
// this.dataType = DataTypeEnum.TIMESTAMP;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain;
|
|
||||||
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字段信息 VO
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class FieldsVo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字段名称
|
|
||||||
*/
|
|
||||||
private String fieldName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字段数据类型
|
|
||||||
*/
|
|
||||||
private String dataType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字段字节大小
|
|
||||||
*/
|
|
||||||
private Integer size;
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
public class IotSequential extends BaseEntity {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS" , timezone = "GMT+8")
|
|
||||||
private Timestamp statetime;
|
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS" , timezone = "GMT+8")
|
|
||||||
private Timestamp endtime;
|
|
||||||
|
|
||||||
private String deviceid;
|
|
||||||
|
|
||||||
private String eventtime;
|
|
||||||
|
|
||||||
private String serviceid;
|
|
||||||
|
|
||||||
private String devices;
|
|
||||||
|
|
||||||
public String getDeviceid() {
|
|
||||||
return deviceid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeviceid(String deviceid) {
|
|
||||||
this.deviceid = deviceid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEventtime() {
|
|
||||||
return eventtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEventtime(String eventtime) {
|
|
||||||
this.eventtime = eventtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getServiceid() {
|
|
||||||
return serviceid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setServiceid(String serviceid) {
|
|
||||||
this.serviceid = serviceid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDevices() {
|
|
||||||
return devices;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDevices(String devices) {
|
|
||||||
this.devices = devices;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Timestamp getStatetime() {
|
|
||||||
return statetime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatetime(Timestamp statetime) {
|
|
||||||
this.statetime = statetime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Timestamp getEndtime() {
|
|
||||||
return endtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEndtime(Timestamp endtime) {
|
|
||||||
this.endtime = endtime;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 统计的时间数据
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class MessageCountVo {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 时间
|
|
||||||
*/
|
|
||||||
private String time;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据值
|
|
||||||
*/
|
|
||||||
private Object data;
|
|
||||||
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class ProductSuperTableModel {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS", timezone = "GMT+8")
|
|
||||||
private Timestamp ts;
|
|
||||||
|
|
||||||
private String superTableName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* columnsName,columnsProperty
|
|
||||||
*/
|
|
||||||
private HashMap<Optional, Optional> columns;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* tagsName,tagsProperty
|
|
||||||
*/
|
|
||||||
private HashMap<Optional, Optional> tags;
|
|
||||||
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class SelectDto {
|
|
||||||
|
|
||||||
// @NotBlank(message = "invalid operation: dataBaseName can not be empty")
|
|
||||||
private String dataBaseName;
|
|
||||||
|
|
||||||
// @NotBlank(message = "invalid operation: tableName can not be empty")
|
|
||||||
private String tableName;
|
|
||||||
|
|
||||||
// @NotBlank(message = "invalid operation: fieldName can not be empty")
|
|
||||||
private String fieldName;
|
|
||||||
|
|
||||||
// @NotNull(message = "invalid operation: startTime can not be null")
|
|
||||||
private Long startTime;
|
|
||||||
|
|
||||||
// @NotNull(message = "invalid operation: endTime can not be null")
|
|
||||||
private Long endTime;
|
|
||||||
|
|
||||||
private String type;
|
|
||||||
|
|
||||||
private Set<Integer> orgIds;
|
|
||||||
|
|
||||||
private String deviceId;
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class SuperTableDto extends BaseEntity {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超级表的表结构(业务相关)
|
|
||||||
* 第一个字段的数据类型必须为timestamp
|
|
||||||
* 字符相关数据类型必须指定大小
|
|
||||||
* 字段名称和字段数据类型不能为空
|
|
||||||
*/
|
|
||||||
// @NotEmpty(message = "invalid operation: schemaFields can not be empty")
|
|
||||||
private List<Fields> schemaFields;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超级表的标签字段,可以作为子表在超级表里的标识
|
|
||||||
* 字符相关数据类型必须指定大小
|
|
||||||
* 字段名称和字段数据类型不能为空
|
|
||||||
*/
|
|
||||||
// @NotEmpty(message = "invalid operation: tagsFields can not be empty")
|
|
||||||
private List<Fields> tagsFields;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字段信息对象,超级表添加列时使用该属性
|
|
||||||
*/
|
|
||||||
private Fields fields;
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class TableDto extends BaseEntity {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超级表普通列字段的值
|
|
||||||
* 值需要与创建超级表时普通列字段的数据类型对应上
|
|
||||||
*/
|
|
||||||
private List<Fields> schemaFieldValues;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超级表标签字段的值
|
|
||||||
* 值需要与创建超级表时标签字段的数据类型对应上
|
|
||||||
*/
|
|
||||||
private List<Fields> tagsFieldValues;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 表名称
|
|
||||||
*/
|
|
||||||
private String tableName;
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class TagsSelectDao {
|
|
||||||
|
|
||||||
// @NotBlank(message = "invalid operation: dataBaseName can not be empty")
|
|
||||||
private String dataBaseName;
|
|
||||||
|
|
||||||
// @NotBlank(message = "invalid operation: stableName can not be empty")
|
|
||||||
private String stableName;
|
|
||||||
|
|
||||||
// @NotBlank(message = "invalid operation: tagsName can not be empty")
|
|
||||||
private String tagsName;
|
|
||||||
|
|
||||||
// @NotNull(message = "invalid operation: startTime can not be null")
|
|
||||||
private Long startTime;
|
|
||||||
|
|
||||||
// @NotNull(message = "invalid operation: endTime can not be null")
|
|
||||||
private Long endTime;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
public class Weather {
|
|
||||||
|
|
||||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS" , timezone = "GMT+8")
|
|
||||||
private Timestamp ts;
|
|
||||||
private Float temperature;
|
|
||||||
private Float humidity;
|
|
||||||
private String location;
|
|
||||||
private String note;
|
|
||||||
private int groupId;
|
|
||||||
|
|
||||||
public Weather() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Weather(Timestamp ts, float temperature, float humidity) {
|
|
||||||
this.ts = ts;
|
|
||||||
this.temperature = temperature;
|
|
||||||
this.humidity = humidity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Timestamp getTs() {
|
|
||||||
return ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTs(Timestamp ts) {
|
|
||||||
this.ts = ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Float getTemperature() {
|
|
||||||
return temperature;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTemperature(Float temperature) {
|
|
||||||
this.temperature = temperature;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Float getHumidity() {
|
|
||||||
return humidity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHumidity(Float humidity) {
|
|
||||||
this.humidity = humidity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLocation() {
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLocation(String location) {
|
|
||||||
this.location = location;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getGroupId() {
|
|
||||||
return groupId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGroupId(int groupId) {
|
|
||||||
this.groupId = groupId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNote() {
|
|
||||||
return note;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNote(String note) {
|
|
||||||
this.note = note;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,51 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
/**
|
||||||
|
* 查询DO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SelectDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库名称
|
||||||
|
*/
|
||||||
|
private String dataBaseName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超级表名称
|
||||||
|
*/
|
||||||
|
private String tableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询字段
|
||||||
|
*/
|
||||||
|
private String fieldName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始时间
|
||||||
|
*/
|
||||||
|
private Long startTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束时间
|
||||||
|
*/
|
||||||
|
private Long endTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询类型
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询条件
|
||||||
|
*/
|
||||||
|
private Set<Integer> orgIds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备ID
|
||||||
|
*/
|
||||||
|
private String deviceId;
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
package cn.iocoder.yudao.module.iot.domain.visual;
|
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class SelectVisualDto {
|
public class SelectVisualDO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据库名称
|
* 数据库名称
|
@ -1,27 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.iot.domain.BaseEntity;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class TableDO extends BaseEntity {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超级表普通列字段的值
|
|
||||||
* 值需要与创建超级表时普通列字段的数据类型对应上
|
|
||||||
*/
|
|
||||||
private List<TdFieldDO> schemaFieldValues;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超级表标签字段的值
|
|
||||||
* 值需要与创建超级表时标签字段的数据类型对应上
|
|
||||||
*/
|
|
||||||
private List<TdFieldDO> tagsFieldValues;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 表名称
|
|
||||||
*/
|
|
||||||
private String tableName;
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TableData 类用于存储和操作 TDengine 表数据
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class TableData {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超级表普通列字段的名称
|
|
||||||
*/
|
|
||||||
private List<String> schemaFieldList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超级表普通列字段的值
|
|
||||||
* 值需要与创建超级表时普通列字段的数据类型对应上
|
|
||||||
*/
|
|
||||||
private List<Object> schemaValueList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超级表标签字段的名称
|
|
||||||
*/
|
|
||||||
private List<String> tagsFieldList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超级表标签字段的值
|
|
||||||
* 值需要与创建超级表时标签字段的数据类型对应上
|
|
||||||
*/
|
|
||||||
private List<Object> tagsValueList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 表名称
|
|
||||||
*/
|
|
||||||
private String tableName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 超级表名称
|
|
||||||
*/
|
|
||||||
private String superTableName;
|
|
||||||
}
|
|
@ -0,0 +1,36 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tags查询DO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TagsSelectDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库名称
|
||||||
|
*/
|
||||||
|
private String dataBaseName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超级表名称
|
||||||
|
*/
|
||||||
|
private String stableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tags名称
|
||||||
|
*/
|
||||||
|
private String tagsName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tags值
|
||||||
|
*/
|
||||||
|
private Long startTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tags值
|
||||||
|
*/
|
||||||
|
private Long endTime;
|
||||||
|
|
||||||
|
}
|
@ -19,11 +19,6 @@ public class TdFieldDO {
|
|||||||
*/
|
*/
|
||||||
private String fieldName;
|
private String fieldName;
|
||||||
|
|
||||||
/**
|
|
||||||
* 字段值
|
|
||||||
*/
|
|
||||||
private Object fieldValue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 字段类型
|
* 字段类型
|
||||||
*/
|
*/
|
||||||
@ -34,6 +29,11 @@ public class TdFieldDO {
|
|||||||
*/
|
*/
|
||||||
private Integer dataLength = 0;
|
private Integer dataLength = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段值
|
||||||
|
*/
|
||||||
|
private Object fieldValue;
|
||||||
|
|
||||||
public TdFieldDO(String fieldName, String dataType, Integer dataLength) {
|
public TdFieldDO(String fieldName, String dataType, Integer dataLength) {
|
||||||
this.fieldName = fieldName;
|
this.fieldName = fieldName;
|
||||||
this.dataType = dataType;
|
this.dataType = dataType;
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的数据库
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class TdTableDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库名称
|
||||||
|
*/
|
||||||
|
private String dataBaseName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超级表名称
|
||||||
|
*/
|
||||||
|
private String superTableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表名称
|
||||||
|
*/
|
||||||
|
private String tableName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COLUMN 字段
|
||||||
|
*/
|
||||||
|
private TdFieldDO column;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TAG 字段
|
||||||
|
*/
|
||||||
|
private TdFieldDO tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* COLUMN 字段 - 列表
|
||||||
|
*/
|
||||||
|
private List<TdFieldDO> columns;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TAG 字段 - 列表
|
||||||
|
*/
|
||||||
|
private List<TdFieldDO> tags;
|
||||||
|
|
||||||
|
public TdTableDO(String dataBaseName, String superTableName, List<TdFieldDO> columns, List<TdFieldDO> tags) {
|
||||||
|
this.dataBaseName = dataBaseName;
|
||||||
|
this.superTableName = superTableName;
|
||||||
|
this.columns = columns;
|
||||||
|
this.tags = tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TdTableDO(String dataBaseName, String superTableName) {
|
||||||
|
this.dataBaseName = dataBaseName;
|
||||||
|
this.superTableName = superTableName;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.tdengine;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
|
||||||
|
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||||
|
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的数据写入 Mapper
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
@DS("tdengine")
|
||||||
|
public interface TdEngineDataWriterMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入数据 - 指定列插入数据
|
||||||
|
*
|
||||||
|
* @param table 数据
|
||||||
|
* dataBaseName 数据库名
|
||||||
|
* tableName 表名
|
||||||
|
* columns 列
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
void insertData(TdTableDO table);
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.tdengine;
|
||||||
|
|
||||||
|
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||||
|
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的数据库 Mapper
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
@DS("tdengine")
|
||||||
|
public interface TdEngineDatabaseMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建数据库
|
||||||
|
* SQL:CREATE DATABASE [IF NOT EXISTS] db_name [database_options];
|
||||||
|
*
|
||||||
|
* @param dataBaseName 数据库名称
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
void createDatabase(@Param("dataBaseName") String dataBaseName);
|
||||||
|
}
|
@ -1,129 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.dal.tdengine;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO;
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
|
|
||||||
import cn.iocoder.yudao.module.iot.domain.FieldsVo;
|
|
||||||
import cn.iocoder.yudao.module.iot.domain.SelectDto;
|
|
||||||
import cn.iocoder.yudao.module.iot.domain.TagsSelectDao;
|
|
||||||
import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto;
|
|
||||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
|
||||||
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Mapper
|
|
||||||
@DS("tdengine")
|
|
||||||
public interface TdEngineMapper {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建数据库
|
|
||||||
*
|
|
||||||
* @param dataBaseName 数据库名称
|
|
||||||
*/
|
|
||||||
@InterceptorIgnore(tenantLine = "true")
|
|
||||||
void createDatabase(@Param("dataBaseName") String dataBaseName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建超级表
|
|
||||||
*
|
|
||||||
* @param schemaFields schema字段
|
|
||||||
* @param tagsFields tags字段
|
|
||||||
* @param dataBaseName 数据库名称
|
|
||||||
* @param superTableName 超级表名称
|
|
||||||
*/
|
|
||||||
@InterceptorIgnore(tenantLine = "true")
|
|
||||||
void createSuperTable(@Param("schemaFields") List<TdFieldDO> schemaFields,
|
|
||||||
@Param("tagsFields") List<TdFieldDO> tagsFields,
|
|
||||||
@Param("dataBaseName") String dataBaseName,
|
|
||||||
@Param("superTableName") String superTableName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查看超级表 - 显示当前数据库下的所有超级表信息
|
|
||||||
* SQL:SHOW STABLES [LIKE tb_name_wildcard];
|
|
||||||
*
|
|
||||||
* @param dataBaseName 数据库名称
|
|
||||||
* @param superTableName 超级表名称
|
|
||||||
*/
|
|
||||||
@InterceptorIgnore(tenantLine = "true")
|
|
||||||
List<Map<String, Object>> showSuperTables(@Param("dataBaseName") String dataBaseName,
|
|
||||||
@Param("superTableName") String superTableName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查看超级表 - 获取超级表的结构信息
|
|
||||||
* SQL:DESCRIBE [db_name.]stb_name;
|
|
||||||
* <p>
|
|
||||||
* * @param dataBaseName 数据库名称
|
|
||||||
* * @param superTableName 超级表名称
|
|
||||||
*/
|
|
||||||
@InterceptorIgnore(tenantLine = "true")
|
|
||||||
List<Map<String, Object>> describeSuperTable(@Param("dataBaseName") String dataBaseName,
|
|
||||||
@Param("superTableName") String superTableName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 为超级表添加列
|
|
||||||
*
|
|
||||||
* @param dataBaseName 数据库名称
|
|
||||||
* @param superTableName 超级表名称
|
|
||||||
* @param field 字段信息
|
|
||||||
*/
|
|
||||||
@InterceptorIgnore(tenantLine = "true")
|
|
||||||
void addColumnForSuperTable(@Param("dataBaseName") String dataBaseName,
|
|
||||||
@Param("superTableName") String superTableName,
|
|
||||||
@Param("field") TdFieldDO field);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 为超级表删除列
|
|
||||||
*
|
|
||||||
* @param dataBaseName 数据库名称
|
|
||||||
* @param superTableName 超级表名称
|
|
||||||
* @param field 字段信息
|
|
||||||
*/
|
|
||||||
@InterceptorIgnore(tenantLine = "true")
|
|
||||||
void dropColumnForSuperTable(@Param("dataBaseName") String dataBaseName,
|
|
||||||
@Param("superTableName") String superTableName,
|
|
||||||
@Param("field") TdFieldDO field);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建表 - 创建超级表的子表
|
|
||||||
*
|
|
||||||
* @param tableDO 表信息
|
|
||||||
*/
|
|
||||||
@InterceptorIgnore(tenantLine = "true")
|
|
||||||
void createTable(TableDO tableDO);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 插入数据 - 指定列插入数据
|
|
||||||
*
|
|
||||||
* @param tableDto 数据
|
|
||||||
*/
|
|
||||||
@InterceptorIgnore(tenantLine = "true")
|
|
||||||
void insertData(TableDO tableDto);
|
|
||||||
|
|
||||||
List<Map<String, Object>> selectByTimestamp(SelectDto selectDto);
|
|
||||||
|
|
||||||
|
|
||||||
void addTagForSuperTable(@Param("superTableName") String superTableName,
|
|
||||||
@Param("fieldsVo") FieldsVo fieldsVo);
|
|
||||||
|
|
||||||
void dropTagForSuperTable(@Param("superTableName") String superTableName,
|
|
||||||
@Param("fieldsVo") FieldsVo fieldsVo);
|
|
||||||
|
|
||||||
Map<String, Long> getCountByTimestamp(SelectDto selectDto);
|
|
||||||
|
|
||||||
Map<String, Object> getLastData(SelectDto selectDto);
|
|
||||||
|
|
||||||
@InterceptorIgnore(tenantLine = "true")
|
|
||||||
List<Map<String, Object>> getHistoryData(SelectVisualDto selectVisualDto);
|
|
||||||
|
|
||||||
List<Map<String, Object>> getRealtimeData(SelectVisualDto selectVisualDto);
|
|
||||||
|
|
||||||
List<Map<String, Object>> getAggregateData(SelectVisualDto selectVisualDto);
|
|
||||||
|
|
||||||
List<Map<String, Object>> getLastDataByTags(TagsSelectDao tagsSelectDao);
|
|
||||||
|
|
||||||
@InterceptorIgnore(tenantLine = "true")
|
|
||||||
Long getHistoryCount(SelectVisualDto selectVisualDto);
|
|
||||||
}
|
|
@ -0,0 +1,85 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.tdengine;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO;
|
||||||
|
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||||
|
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的查询 Mapper
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
@DS("tdengine")
|
||||||
|
public interface TdEngineQueryMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据时间戳查询数据
|
||||||
|
*
|
||||||
|
* @param selectDO 查询条件
|
||||||
|
* @return 查询结果
|
||||||
|
*/
|
||||||
|
List<Map<String, Object>> selectByTimestamp(SelectDO selectDO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据时间戳获取数据条数
|
||||||
|
*
|
||||||
|
* @param selectDO 查询条件
|
||||||
|
* @return 数据条数
|
||||||
|
*/
|
||||||
|
Map<String, Long> getCountByTimestamp(SelectDO selectDO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取最新数据
|
||||||
|
*
|
||||||
|
* @param selectDO 查询条件
|
||||||
|
* @return 最新数据
|
||||||
|
*/
|
||||||
|
Map<String, Object> getLastData(SelectDO selectDO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取历史数据
|
||||||
|
*
|
||||||
|
* @param selectVisualDO 查询条件
|
||||||
|
* @return 历史数据列表
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
List<Map<String, Object>> getHistoryData(SelectVisualDO selectVisualDO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取实时数据
|
||||||
|
*
|
||||||
|
* @param selectVisualDO 查询条件
|
||||||
|
* @return 实时数据列表
|
||||||
|
*/
|
||||||
|
List<Map<String, Object>> getRealtimeData(SelectVisualDO selectVisualDO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取聚合数据
|
||||||
|
*
|
||||||
|
* @param selectVisualDO 查询条件
|
||||||
|
* @return 聚合数据列表
|
||||||
|
*/
|
||||||
|
List<Map<String, Object>> getAggregateData(SelectVisualDO selectVisualDO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据标签获取最新数据
|
||||||
|
*
|
||||||
|
* @param tagsSelectDO 查询条件
|
||||||
|
* @return 最新数据列表
|
||||||
|
*/
|
||||||
|
List<Map<String, Object>> getLastDataByTags(TagsSelectDO tagsSelectDO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取历史数据条数
|
||||||
|
*
|
||||||
|
* @param selectVisualDO 查询条件
|
||||||
|
* @return 数据条数
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
Long getHistoryCount(SelectVisualDO selectVisualDO);
|
||||||
|
}
|
@ -0,0 +1,111 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.tdengine;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
|
||||||
|
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||||
|
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的超级表 Mapper
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
@DS("tdengine")
|
||||||
|
public interface TdEngineSuperTableMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建超级表
|
||||||
|
* SQL:CREATE STABLE [IF NOT EXISTS] stb_name (create_definition [, create_definition] ...) TAGS (create_definition [, create_definition] ...) [table_options];
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* columns 列信息
|
||||||
|
* tags 标签信息
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
void createSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看超级表 - 显示当前数据库下的所有超级表信息
|
||||||
|
* SQL:SHOW STABLES [LIKE tb_name_wildcard];
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
List<Map<String, Object>> showSuperTables(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看超级表 - 获取超级表的结构信息
|
||||||
|
* SQL:DESCRIBE [db_name.]stb_name;
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
List<Map<String, Object>> describeSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改超级表 - 增加列
|
||||||
|
* SQL:ALTER STABLE stb_name ADD COLUMN col_name column_type;
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* column 列信息
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
void addColumnForSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改超级表 - 删除列
|
||||||
|
* SQL:ALTER STABLE stb_name DROP COLUMN col_name;
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* column 列信息
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
void dropColumnForSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改超级表 - 修改列宽
|
||||||
|
* SQL:ALTER STABLE stb_name MODIFY COLUMN col_name data_type(length);
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* column 列信息
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
void modifyColumnWidthForSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改超级表 - 为超级表添加标签
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* tag 标签信息
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
void addTagForSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改超级表 - 为超级表删除标签
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* tag 标签信息
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
void dropTagForSuperTable(TdTableDO superTable);
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.dal.tdengine;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
|
||||||
|
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||||
|
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的表 Mapper
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
@DS("tdengine")
|
||||||
|
public interface TdEngineTableMapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建子表 - 创建子表
|
||||||
|
* SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...);
|
||||||
|
*
|
||||||
|
* @param table 表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* tableName 子表名称
|
||||||
|
* tags TAG 字段
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
void createTable(TdTableDO table);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建子表 - 创建子表并指定标签的值
|
||||||
|
* SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...);
|
||||||
|
*
|
||||||
|
* @param table 表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* tableName 子表名称
|
||||||
|
* tags TAG 字段
|
||||||
|
*/
|
||||||
|
@InterceptorIgnore(tenantLine = "true")
|
||||||
|
void createTableWithTags(TdTableDO table);
|
||||||
|
|
||||||
|
}
|
@ -6,13 +6,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|||||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO;
|
||||||
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.IotDeviceDataDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO;
|
import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper;
|
|
||||||
import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto;
|
|
||||||
import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
|
import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
|
||||||
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.tdengine.TdEngineQueryService;
|
||||||
import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService;
|
import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
@ -39,13 +39,12 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService {
|
|||||||
private IotThingModelMessageService thingModelMessageService;
|
private IotThingModelMessageService thingModelMessageService;
|
||||||
@Resource
|
@Resource
|
||||||
private IotThinkModelFunctionService thinkModelFunctionService;
|
private IotThinkModelFunctionService thinkModelFunctionService;
|
||||||
|
@Resource
|
||||||
|
private TdEngineQueryService tdEngineQueryService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private DeviceDataRedisDAO deviceDataRedisDAO;
|
private DeviceDataRedisDAO deviceDataRedisDAO;
|
||||||
|
|
||||||
@Resource
|
|
||||||
private TdEngineMapper tdEngineMapper;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveDeviceData(String productKey, String deviceName, String message) {
|
public void saveDeviceData(String productKey, String deviceName, String message) {
|
||||||
// 1. 根据产品 key 和设备名称,获得设备信息
|
// 1. 根据产品 key 和设备名称,获得设备信息
|
||||||
@ -112,18 +111,18 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService {
|
|||||||
// 1. 获取设备信息
|
// 1. 获取设备信息
|
||||||
IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId());
|
IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId());
|
||||||
// 2. 获取设备属性历史数据
|
// 2. 获取设备属性历史数据
|
||||||
SelectVisualDto selectVisualDto = new SelectVisualDto();
|
SelectVisualDO selectVisualDO = new SelectVisualDO();
|
||||||
selectVisualDto.setDataBaseName(getDatabaseName());
|
selectVisualDO.setDataBaseName(getDatabaseName());
|
||||||
selectVisualDto.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName()));
|
selectVisualDO.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName()));
|
||||||
selectVisualDto.setFieldName(deviceDataReqVO.getIdentifier());
|
selectVisualDO.setFieldName(deviceDataReqVO.getIdentifier());
|
||||||
selectVisualDto.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime());
|
selectVisualDO.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime());
|
||||||
selectVisualDto.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime());
|
selectVisualDO.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime());
|
||||||
Map<String, Object> params = new HashMap<>();
|
Map<String, Object> params = new HashMap<>();
|
||||||
params.put("rows", deviceDataReqVO.getPageSize());
|
params.put("rows", deviceDataReqVO.getPageSize());
|
||||||
params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize());
|
params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize());
|
||||||
selectVisualDto.setParams(params);
|
selectVisualDO.setParams(params);
|
||||||
pageResult.setList(tdEngineMapper.getHistoryData(selectVisualDto));
|
pageResult.setList(tdEngineQueryService.getHistoryData(selectVisualDO));
|
||||||
pageResult.setTotal(tdEngineMapper.getHistoryCount(selectVisualDto));
|
pageResult.setTotal(tdEngineQueryService.getHistoryCount(selectVisualDO));
|
||||||
return pageResult;
|
return pageResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,26 +1,15 @@
|
|||||||
package cn.iocoder.yudao.module.iot.service.tdengine;
|
package cn.iocoder.yudao.module.iot.service.tdengine;
|
||||||
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelRespVO;
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据结构接口
|
* IoT 超级表服务,负责根据物模型创建和更新超级表,以及创建超级表的子表等操作。
|
||||||
*/
|
*/
|
||||||
public interface IotDbStructureDataService {
|
public interface IotSuperTableService {
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建物模型定义
|
|
||||||
*/
|
|
||||||
void createSuperTable(ThingModelRespVO thingModel, Integer deviceType);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新物模型定义
|
|
||||||
*/
|
|
||||||
void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建超级表数据模型
|
* 创建超级表数据模型
|
@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingMode
|
|||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
|
||||||
import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
|
import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
@ -17,135 +18,19 @@ import org.springframework.stereotype.Service;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IoT 超级表服务实现类,负责根据物模型创建和更新超级表,以及创建超级表的子表等操作。
|
||||||
|
*/
|
||||||
@Service
|
@Service
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class IotDbStructureDataServiceImpl implements IotDbStructureDataService {
|
public class IotSuperTableServiceImpl implements IotSuperTableService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private IotTdEngineService iotTdEngineService;
|
private TdEngineSuperTableService tdEngineSuperTableService;
|
||||||
|
|
||||||
@Value("${spring.datasource.dynamic.datasource.tdengine.url}")
|
@Value("${spring.datasource.dynamic.datasource.tdengine.url}")
|
||||||
private String url;
|
private String url;
|
||||||
|
|
||||||
@Override
|
|
||||||
public void createSuperTable(ThingModelRespVO thingModel, Integer deviceType) {
|
|
||||||
// 1. 解析物模型,获得字段列表
|
|
||||||
List<TdFieldDO> schemaFields = new ArrayList<>();
|
|
||||||
schemaFields.add(TdFieldDO.builder()
|
|
||||||
.fieldName("time")
|
|
||||||
.dataType("TIMESTAMP")
|
|
||||||
.build());
|
|
||||||
schemaFields.addAll(FieldParser.parse(thingModel));
|
|
||||||
|
|
||||||
// 3. 设置超级表的标签
|
|
||||||
List<TdFieldDO> tagsFields = Arrays.asList(
|
|
||||||
TdFieldDO.builder().fieldName("product_key").dataType("NCHAR").dataLength(64).build(),
|
|
||||||
TdFieldDO.builder().fieldName("device_key").dataType("NCHAR").dataLength(64).build(),
|
|
||||||
TdFieldDO.builder().fieldName("device_name").dataType("NCHAR").dataLength(64).build(),
|
|
||||||
TdFieldDO.builder().fieldName("device_type").dataType("INT").build()
|
|
||||||
);
|
|
||||||
|
|
||||||
// 4. 获取超级表的名称
|
|
||||||
String superTableName = getProductPropertySTableName(deviceType, thingModel.getProductKey());
|
|
||||||
|
|
||||||
// 5. 创建超级表
|
|
||||||
String dataBaseName = getDatabaseName();
|
|
||||||
iotTdEngineService.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType) {
|
|
||||||
try {
|
|
||||||
String tbName = getProductPropertySTableName(deviceType, thingModel.getProductKey());
|
|
||||||
List<TdFieldDO> oldFields = getTableFields(tbName);
|
|
||||||
List<TdFieldDO> newFields = FieldParser.parse(thingModel);
|
|
||||||
|
|
||||||
updateTableFields(tbName, oldFields, newFields);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("更新物模型超级表失败", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取表字段
|
|
||||||
private List<TdFieldDO> getTableFields(String tableName) {
|
|
||||||
List<TdFieldDO> fields = new ArrayList<>();
|
|
||||||
// 获取超级表的描述信息
|
|
||||||
List<Map<String, Object>> maps = iotTdEngineService.describeSuperTable(getDatabaseName(), tableName);
|
|
||||||
if (maps != null) {
|
|
||||||
// 过滤掉 note 字段为 TAG 的记录和 time 字段
|
|
||||||
List<Map<String, Object>> filteredMaps = maps.stream()
|
|
||||||
.filter(map -> !"TAG".equals(map.get("note")))
|
|
||||||
.filter(map -> !"time".equals(map.get("field")))
|
|
||||||
.toList();
|
|
||||||
// 解析字段信息
|
|
||||||
fields = FieldParser.parse(filteredMaps.stream()
|
|
||||||
.map(map -> List.of(map.get("field"), map.get("type"), map.get("length")))
|
|
||||||
.collect(Collectors.toList()));
|
|
||||||
}
|
|
||||||
return fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新表字段
|
|
||||||
private void updateTableFields(String tableName, List<TdFieldDO> oldFields, List<TdFieldDO> newFields) {
|
|
||||||
// 获取新增字段
|
|
||||||
List<TdFieldDO> addFields = getAddFields(oldFields, newFields);
|
|
||||||
// 获取修改字段
|
|
||||||
List<TdFieldDO> modifyFields = getModifyFields(oldFields, newFields);
|
|
||||||
// 获取删除字段
|
|
||||||
List<TdFieldDO> dropFields = getDropFields(oldFields, newFields);
|
|
||||||
|
|
||||||
String dataBaseName = getDatabaseName();
|
|
||||||
// 添加新增字段
|
|
||||||
if (CollUtil.isNotEmpty(addFields)) {
|
|
||||||
iotTdEngineService.addColumnForSuperTable(dataBaseName, tableName, addFields);
|
|
||||||
}
|
|
||||||
// 删除旧字段
|
|
||||||
if (CollUtil.isNotEmpty(dropFields)) {
|
|
||||||
iotTdEngineService.dropColumnForSuperTable(dataBaseName, tableName, dropFields);
|
|
||||||
}
|
|
||||||
// 修改字段(先删除再添加)
|
|
||||||
if (CollUtil.isNotEmpty(modifyFields)) {
|
|
||||||
iotTdEngineService.dropColumnForSuperTable(dataBaseName, tableName, modifyFields);
|
|
||||||
iotTdEngineService.addColumnForSuperTable(dataBaseName, tableName, modifyFields);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取新增字段
|
|
||||||
private List<TdFieldDO> getAddFields(List<TdFieldDO> oldFields, List<TdFieldDO> newFields) {
|
|
||||||
Set<String> oldFieldNames = oldFields.stream()
|
|
||||||
.map(TdFieldDO::getFieldName)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
return newFields.stream()
|
|
||||||
.filter(f -> !oldFieldNames.contains(f.getFieldName()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取修改字段
|
|
||||||
private List<TdFieldDO> getModifyFields(List<TdFieldDO> oldFields, List<TdFieldDO> newFields) {
|
|
||||||
Map<String, TdFieldDO> oldFieldMap = oldFields.stream()
|
|
||||||
.collect(Collectors.toMap(TdFieldDO::getFieldName, f -> f));
|
|
||||||
|
|
||||||
return newFields.stream()
|
|
||||||
.filter(f -> {
|
|
||||||
TdFieldDO oldField = oldFieldMap.get(f.getFieldName());
|
|
||||||
return oldField != null &&
|
|
||||||
(!oldField.getDataType().equals(f.getDataType()) ||
|
|
||||||
!Objects.equals(oldField.getDataLength(), f.getDataLength()));
|
|
||||||
})
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取删除字段
|
|
||||||
private List<TdFieldDO> getDropFields(List<TdFieldDO> oldFields, List<TdFieldDO> newFields) {
|
|
||||||
Set<String> newFieldNames = newFields.stream()
|
|
||||||
.map(TdFieldDO::getFieldName)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
return oldFields.stream()
|
|
||||||
.filter(f -> !"time".equals(f.getFieldName()) && !"device_id".equals(f.getFieldName()))
|
|
||||||
.filter(f -> !newFieldNames.contains(f.getFieldName()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createSuperTableDataModel(IotProductDO product, List<IotThinkModelFunctionDO> functionList) {
|
public void createSuperTableDataModel(IotProductDO product, List<IotThinkModelFunctionDO> functionList) {
|
||||||
ThingModelRespVO thingModel = buildThingModel(product, functionList);
|
ThingModelRespVO thingModel = buildThingModel(product, functionList);
|
||||||
@ -155,9 +40,9 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String superTableName = getProductPropertySTableName(product.getDeviceType(), product.getProductKey());
|
String superTableName = getSuperTableName(product.getDeviceType(), product.getProductKey());
|
||||||
String dataBaseName = getDatabaseName();
|
String databaseName = getDatabaseName();
|
||||||
Integer tableExists = iotTdEngineService.checkSuperTableExists(dataBaseName, superTableName);
|
Integer tableExists = tdEngineSuperTableService.checkSuperTableExists(new TdTableDO(databaseName, superTableName));
|
||||||
|
|
||||||
if (tableExists != null && tableExists > 0) {
|
if (tableExists != null && tableExists > 0) {
|
||||||
updateSuperTable(thingModel, product.getDeviceType());
|
updateSuperTable(thingModel, product.getDeviceType());
|
||||||
@ -166,40 +51,202 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建超级表
|
||||||
|
*/
|
||||||
|
private void createSuperTable(ThingModelRespVO thingModel, Integer deviceType) {
|
||||||
|
// 解析物模型,获取字段列表
|
||||||
|
List<TdFieldDO> schemaFields = new ArrayList<>();
|
||||||
|
schemaFields.add(TdFieldDO.builder()
|
||||||
|
.fieldName("time")
|
||||||
|
.dataType("TIMESTAMP")
|
||||||
|
.build());
|
||||||
|
schemaFields.addAll(FieldParser.parse(thingModel));
|
||||||
|
|
||||||
|
// 设置超级表的标签
|
||||||
|
List<TdFieldDO> tagsFields = List.of(
|
||||||
|
TdFieldDO.builder().fieldName("product_key").dataType("NCHAR").dataLength(64).build(),
|
||||||
|
TdFieldDO.builder().fieldName("device_key").dataType("NCHAR").dataLength(64).build(),
|
||||||
|
TdFieldDO.builder().fieldName("device_name").dataType("NCHAR").dataLength(64).build(),
|
||||||
|
TdFieldDO.builder().fieldName("device_type").dataType("INT").build()
|
||||||
|
);
|
||||||
|
|
||||||
|
// 获取超级表的名称和数据库名称
|
||||||
|
String superTableName = getSuperTableName(deviceType, thingModel.getProductKey());
|
||||||
|
String databaseName = getDatabaseName();
|
||||||
|
|
||||||
|
// 创建超级表
|
||||||
|
tdEngineSuperTableService.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新超级表
|
||||||
|
*/
|
||||||
|
private void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType) {
|
||||||
|
String superTableName = getSuperTableName(deviceType, thingModel.getProductKey());
|
||||||
|
try {
|
||||||
|
List<TdFieldDO> oldFields = getTableFields(superTableName);
|
||||||
|
List<TdFieldDO> newFields = FieldParser.parse(thingModel);
|
||||||
|
|
||||||
|
updateTableFields(superTableName, oldFields, newFields);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("更新物模型超级表失败: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取表的字段信息
|
||||||
|
*/
|
||||||
|
private List<TdFieldDO> getTableFields(String tableName) {
|
||||||
|
List<Map<String, Object>> tableDescription = tdEngineSuperTableService.describeSuperTable(new TdTableDO(getDatabaseName(), tableName));
|
||||||
|
if (CollUtil.isEmpty(tableDescription)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return tableDescription.stream()
|
||||||
|
.filter(map -> !"TAG".equals(map.get("note")))
|
||||||
|
.filter(map -> !"time".equals(map.get("field")))
|
||||||
|
.map(map -> TdFieldDO.builder()
|
||||||
|
.fieldName((String) map.get("field"))
|
||||||
|
.dataType((String) map.get("type"))
|
||||||
|
.dataLength((Integer) map.get("length"))
|
||||||
|
.build())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新表的字段,包括新增、修改和删除字段
|
||||||
|
*/
|
||||||
|
private void updateTableFields(String tableName, List<TdFieldDO> oldFields, List<TdFieldDO> newFields) {
|
||||||
|
String databaseName = getDatabaseName();
|
||||||
|
|
||||||
|
// 获取新增、修改、删除的字段
|
||||||
|
List<TdFieldDO> addFields = getAddFields(oldFields, newFields);
|
||||||
|
List<TdFieldDO> modifyFields = getModifyFields(oldFields, newFields);
|
||||||
|
List<TdFieldDO> dropFields = getDropFields(oldFields, newFields);
|
||||||
|
|
||||||
|
// 添加新增字段
|
||||||
|
if (CollUtil.isNotEmpty(addFields)) {
|
||||||
|
tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder()
|
||||||
|
.dataBaseName(databaseName)
|
||||||
|
.superTableName(tableName)
|
||||||
|
.columns(addFields)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
// 删除旧字段
|
||||||
|
if (CollUtil.isNotEmpty(dropFields)) {
|
||||||
|
tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder()
|
||||||
|
.dataBaseName(databaseName)
|
||||||
|
.superTableName(tableName)
|
||||||
|
.columns(dropFields)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
// 修改字段(先删除再添加)
|
||||||
|
if (CollUtil.isNotEmpty(modifyFields)) {
|
||||||
|
tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder()
|
||||||
|
.dataBaseName(databaseName)
|
||||||
|
.superTableName(tableName)
|
||||||
|
.columns(modifyFields)
|
||||||
|
.build());
|
||||||
|
tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder()
|
||||||
|
.dataBaseName(databaseName)
|
||||||
|
.superTableName(tableName)
|
||||||
|
.columns(addFields)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取需要新增的字段
|
||||||
|
*/
|
||||||
|
private List<TdFieldDO> getAddFields(List<TdFieldDO> oldFields, List<TdFieldDO> newFields) {
|
||||||
|
Set<String> oldFieldNames = oldFields.stream()
|
||||||
|
.map(TdFieldDO::getFieldName)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
return newFields.stream()
|
||||||
|
.filter(f -> !oldFieldNames.contains(f.getFieldName()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取需要修改的字段
|
||||||
|
*/
|
||||||
|
private List<TdFieldDO> getModifyFields(List<TdFieldDO> oldFields, List<TdFieldDO> newFields) {
|
||||||
|
Map<String, TdFieldDO> oldFieldMap = oldFields.stream()
|
||||||
|
.collect(Collectors.toMap(TdFieldDO::getFieldName, f -> f));
|
||||||
|
|
||||||
|
return newFields.stream()
|
||||||
|
.filter(f -> {
|
||||||
|
TdFieldDO oldField = oldFieldMap.get(f.getFieldName());
|
||||||
|
return oldField != null && (
|
||||||
|
!oldField.getDataType().equals(f.getDataType()) ||
|
||||||
|
!Objects.equals(oldField.getDataLength(), f.getDataLength())
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取需要删除的字段
|
||||||
|
*/
|
||||||
|
private List<TdFieldDO> getDropFields(List<TdFieldDO> oldFields, List<TdFieldDO> newFields) {
|
||||||
|
Set<String> newFieldNames = newFields.stream()
|
||||||
|
.map(TdFieldDO::getFieldName)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
return oldFields.stream()
|
||||||
|
.filter(f -> !"time".equals(f.getFieldName()))
|
||||||
|
.filter(f -> !newFieldNames.contains(f.getFieldName()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建物模型
|
||||||
|
*/
|
||||||
private ThingModelRespVO buildThingModel(IotProductDO product, List<IotThinkModelFunctionDO> functionList) {
|
private ThingModelRespVO buildThingModel(IotProductDO product, List<IotThinkModelFunctionDO> functionList) {
|
||||||
ThingModelRespVO thingModel = new ThingModelRespVO();
|
ThingModelRespVO thingModel = new ThingModelRespVO();
|
||||||
thingModel.setId(product.getId());
|
thingModel.setId(product.getId());
|
||||||
thingModel.setProductKey(product.getProductKey());
|
thingModel.setProductKey(product.getProductKey());
|
||||||
|
|
||||||
ThingModelRespVO.Model model = new ThingModelRespVO.Model();
|
|
||||||
List<ThingModelProperty> properties = functionList.stream()
|
List<ThingModelProperty> properties = functionList.stream()
|
||||||
.filter(function -> IotProductFunctionTypeEnum.PROPERTY.equals(
|
.filter(function -> IotProductFunctionTypeEnum.PROPERTY.equals(
|
||||||
IotProductFunctionTypeEnum.valueOfType(function.getType())))
|
IotProductFunctionTypeEnum.valueOfType(function.getType())))
|
||||||
.map(this::buildThingModelProperty)
|
.map(this::buildThingModelProperty)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
ThingModelRespVO.Model model = new ThingModelRespVO.Model();
|
||||||
model.setProperties(properties);
|
model.setProperties(properties);
|
||||||
thingModel.setModel(model);
|
thingModel.setModel(model);
|
||||||
|
|
||||||
return thingModel;
|
return thingModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建物模型属性
|
||||||
|
*/
|
||||||
private ThingModelProperty buildThingModelProperty(IotThinkModelFunctionDO function) {
|
private ThingModelProperty buildThingModelProperty(IotThinkModelFunctionDO function) {
|
||||||
ThingModelProperty property = BeanUtil.copyProperties(function, ThingModelProperty.class);
|
ThingModelProperty property = BeanUtil.copyProperties(function, ThingModelProperty.class);
|
||||||
property.setDataType(function.getProperty().getDataType());
|
property.setDataType(function.getProperty().getDataType());
|
||||||
return property;
|
return property;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据库名称
|
||||||
|
*/
|
||||||
private String getDatabaseName() {
|
private String getDatabaseName() {
|
||||||
return url.substring(url.lastIndexOf("/") + 1);
|
int index = url.lastIndexOf("/");
|
||||||
|
return index != -1 ? url.substring(index + 1) : url;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getProductPropertySTableName(Integer deviceType, String productKey) {
|
/**
|
||||||
return switch (deviceType) {
|
* 获取超级表名称
|
||||||
case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase();
|
*/
|
||||||
case 2 -> String.format("gateway_%s", productKey).toLowerCase();
|
private String getSuperTableName(Integer deviceType, String productKey) {
|
||||||
default -> String.format("device_%s", productKey).toLowerCase();
|
String prefix = switch (deviceType) {
|
||||||
|
case 1 -> "gateway_sub_";
|
||||||
|
case 2 -> "gateway_";
|
||||||
|
default -> "device_";
|
||||||
};
|
};
|
||||||
|
return (prefix + productKey).toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,142 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.service.tdengine;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO;
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
|
|
||||||
import cn.iocoder.yudao.module.iot.domain.SelectDto;
|
|
||||||
import cn.iocoder.yudao.module.iot.domain.TagsSelectDao;
|
|
||||||
import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TdEngineService
|
|
||||||
*/
|
|
||||||
public interface IotTdEngineService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建数据库
|
|
||||||
*
|
|
||||||
* @param dataBaseName 数据库名称
|
|
||||||
* @throws Exception 异常
|
|
||||||
*/
|
|
||||||
void createDateBase(String dataBaseName) throws Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建超级表
|
|
||||||
*
|
|
||||||
* @param schemaFields schema字段
|
|
||||||
* @param tagsFields tags字段
|
|
||||||
* @param superTableName 超级表名称
|
|
||||||
*/
|
|
||||||
void createSuperTable(List<TdFieldDO> schemaFields, List<TdFieldDO> tagsFields, String dataBaseName, String superTableName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查超级表是否存在
|
|
||||||
*/
|
|
||||||
Integer checkSuperTableExists(String dataBaseName, String superTableName);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取超级表的结构信息
|
|
||||||
*/
|
|
||||||
List<Map<String, Object>> describeSuperTable(String dataBaseName, String superTableName);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 为超级表添加列
|
|
||||||
*
|
|
||||||
* @param dataBaseName 数据库名称
|
|
||||||
* @param superTableName 超级表名称
|
|
||||||
* @param fieldsVo 字段信息
|
|
||||||
*/
|
|
||||||
void addColumnForSuperTable(String dataBaseName, String superTableName, List<TdFieldDO> fieldsVo);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 为超级表删除列
|
|
||||||
*
|
|
||||||
* @param dataBaseName 数据库名称
|
|
||||||
* @param superTableName 超级表名称
|
|
||||||
* @param fieldsVo 字段信息
|
|
||||||
*/
|
|
||||||
void dropColumnForSuperTable(String dataBaseName, String superTableName, List<TdFieldDO> fieldsVo);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 为超级表添加tag
|
|
||||||
*/
|
|
||||||
Long getCountByTimesTamp(SelectDto selectDto) throws Exception;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建表
|
|
||||||
*
|
|
||||||
* @param tableDto 表信息
|
|
||||||
*/
|
|
||||||
void createTable(TableDO tableDto);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 插入数据
|
|
||||||
*
|
|
||||||
* @param tableDto 表信息
|
|
||||||
*/
|
|
||||||
void insertData(TableDO tableDto);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据时间戳查询数据
|
|
||||||
*
|
|
||||||
* @param selectDto 查询条件
|
|
||||||
* @return 数据
|
|
||||||
* @throws Exception 异常
|
|
||||||
*/
|
|
||||||
List<Map<String, Object>> selectByTimesTamp(SelectDto selectDto) throws Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化超级表
|
|
||||||
*
|
|
||||||
* @param msg 消息
|
|
||||||
* @throws Exception 异常
|
|
||||||
*/
|
|
||||||
void initSTableFrame(String msg) throws Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取最新数据
|
|
||||||
*
|
|
||||||
* @param selectDto 查询条件
|
|
||||||
* @return 数据
|
|
||||||
* @throws Exception 异常
|
|
||||||
*/
|
|
||||||
Map<String, Object> getLastData(SelectDto selectDto) throws Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据tag查询最新数据
|
|
||||||
*
|
|
||||||
* @param tagsSelectDao 查询条件
|
|
||||||
* @return 数据
|
|
||||||
*/
|
|
||||||
Map<String, Map<String, Object>> getLastDataByTags(TagsSelectDao tagsSelectDao);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取历史数据
|
|
||||||
*
|
|
||||||
* @param selectVisualDto 查询条件
|
|
||||||
* @return 数据
|
|
||||||
*/
|
|
||||||
List<Map<String, Object>> getHistoryData(SelectVisualDto selectVisualDto);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取实时数据
|
|
||||||
*
|
|
||||||
* @param selectVisualDto 查询条件
|
|
||||||
* @return 数据
|
|
||||||
*/
|
|
||||||
List<Map<String, Object>> getRealtimeData(SelectVisualDto selectVisualDto);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取聚合数据
|
|
||||||
*
|
|
||||||
* @param selectVisualDto 查询条件
|
|
||||||
* @return 数据
|
|
||||||
*/
|
|
||||||
List<Map<String, Object>> getAggregateData(SelectVisualDto selectVisualDto);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,107 +0,0 @@
|
|||||||
package cn.iocoder.yudao.module.iot.service.tdengine;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO;
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper;
|
|
||||||
import cn.iocoder.yudao.module.iot.domain.SelectDto;
|
|
||||||
import cn.iocoder.yudao.module.iot.domain.TagsSelectDao;
|
|
||||||
import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto;
|
|
||||||
import jakarta.annotation.Resource;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Service
|
|
||||||
@Slf4j
|
|
||||||
public class IotTdEngineServiceImpl implements IotTdEngineService {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private TdEngineMapper tdEngineMapper;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void createDateBase(String dataBaseName) {
|
|
||||||
tdEngineMapper.createDatabase(dataBaseName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void createSuperTable(List<TdFieldDO> schemaFields, List<TdFieldDO> tagsFields, String dataBaseName, String superTableName) {
|
|
||||||
tdEngineMapper.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void createTable(TableDO tableDto) {
|
|
||||||
tdEngineMapper.createTable(tableDto);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void insertData(TableDO tableDto) {
|
|
||||||
tdEngineMapper.insertData(tableDto);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Map<String, Object>> selectByTimesTamp(SelectDto selectDto) {
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addColumnForSuperTable(String dataBaseName,String superTableName, List<TdFieldDO> fields) {
|
|
||||||
for (TdFieldDO field : fields) {
|
|
||||||
tdEngineMapper.addColumnForSuperTable(dataBaseName,superTableName, field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dropColumnForSuperTable(String dataBaseName,String superTableName, List<TdFieldDO> fields) {
|
|
||||||
for (TdFieldDO field : fields) {
|
|
||||||
tdEngineMapper.dropColumnForSuperTable(dataBaseName,superTableName, field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long getCountByTimesTamp(SelectDto selectDto) {
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initSTableFrame(String msg) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Object> getLastData(SelectDto selectDto) {
|
|
||||||
return Map.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Map<String, Object>> getLastDataByTags(TagsSelectDao tagsSelectDao) {
|
|
||||||
return Map.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Map<String, Object>> getHistoryData(SelectVisualDto selectVisualDto) {
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Map<String, Object>> getRealtimeData(SelectVisualDto selectVisualDto) {
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Map<String, Object>> getAggregateData(SelectVisualDto selectVisualDto) {
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer checkSuperTableExists(String dataBaseName, String superTableName) {
|
|
||||||
List<Map<String, Object>> results = tdEngineMapper.showSuperTables(dataBaseName, superTableName);
|
|
||||||
return results == null || results.isEmpty() ? 0 : results.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Map<String, Object>> describeSuperTable(String dataBaseName, String superTableName) {
|
|
||||||
return tdEngineMapper.describeSuperTable(dataBaseName, superTableName);
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,5 +14,5 @@ public interface IotThingModelMessageService {
|
|||||||
* @param device 设备
|
* @param device 设备
|
||||||
* @param thingModelMessage 物模型消息
|
* @param thingModelMessage 物模型消息
|
||||||
*/
|
*/
|
||||||
void saveThingModelMessage(IotDeviceDO device,ThingModelMessage thingModelMessage);
|
void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage);
|
||||||
}
|
}
|
@ -6,8 +6,8 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceSt
|
|||||||
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.IotDeviceDataDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO;
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage;
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO;
|
import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO;
|
||||||
@ -23,6 +23,9 @@ import org.springframework.stereotype.Service;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物模型消息 Service 实现类
|
||||||
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class IotThingModelMessageServiceImpl implements IotThingModelMessageService {
|
public class IotThingModelMessageServiceImpl implements IotThingModelMessageService {
|
||||||
@ -35,7 +38,11 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
|
|||||||
@Resource
|
@Resource
|
||||||
private IotDeviceService iotDeviceService;
|
private IotDeviceService iotDeviceService;
|
||||||
@Resource
|
@Resource
|
||||||
private IotTdEngineService iotTdEngineService;
|
private TdEngineTableService tdEngineTableService;
|
||||||
|
@Resource
|
||||||
|
private TdEngineSuperTableService tdEngineSuperTableService;
|
||||||
|
@Resource
|
||||||
|
private TdEngineDataWriterService tdEngineDataWriterService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private DeviceDataRedisDAO deviceDataRedisDAO;
|
private DeviceDataRedisDAO deviceDataRedisDAO;
|
||||||
@ -90,14 +97,11 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建并保存设备属性
|
// 构建并保存设备属性数据
|
||||||
TableDO tableData = new TableDO();
|
tdEngineDataWriterService.insertData(TdTableDO.builder().build()
|
||||||
tableData.setDataBaseName(getDatabaseName());
|
.setDataBaseName(getDatabaseName())
|
||||||
tableData.setSuperTableName(getProductPropertySTableName(device.getDeviceType(), device.getProductKey()));
|
.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName()))
|
||||||
tableData.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName()));
|
.setColumns(schemaFieldValues));
|
||||||
tableData.setSchemaFieldValues(schemaFieldValues);
|
|
||||||
|
|
||||||
iotTdEngineService.insertData(tableData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,7 +139,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
|
|||||||
String superTableName = getProductPropertySTableName(deviceType, productKey);
|
String superTableName = getProductPropertySTableName(deviceType, productKey);
|
||||||
String dataBaseName = getDatabaseName();
|
String dataBaseName = getDatabaseName();
|
||||||
|
|
||||||
List<Map<String, Object>> maps = iotTdEngineService.describeSuperTable(dataBaseName, superTableName);
|
List<Map<String, Object>> maps = tdEngineSuperTableService.describeSuperTable(new TdTableDO(dataBaseName, superTableName));
|
||||||
List<TdFieldDO> tagsFieldValues = new ArrayList<>();
|
List<TdFieldDO> tagsFieldValues = new ArrayList<>();
|
||||||
|
|
||||||
if (maps != null) {
|
if (maps != null) {
|
||||||
@ -159,13 +163,11 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
|
|||||||
|
|
||||||
// 创建设备数据表
|
// 创建设备数据表
|
||||||
String tableName = getDeviceTableName(productKey, deviceName);
|
String tableName = getDeviceTableName(productKey, deviceName);
|
||||||
TableDO tableDto = new TableDO();
|
tdEngineTableService.createTable(TdTableDO.builder().build()
|
||||||
tableDto.setDataBaseName(dataBaseName);
|
.setDataBaseName(dataBaseName)
|
||||||
tableDto.setSuperTableName(superTableName);
|
.setSuperTableName(superTableName)
|
||||||
tableDto.setTableName(tableName);
|
.setTableName(tableName)
|
||||||
tableDto.setTagsFieldValues(tagsFieldValues);
|
.setTags(tagsFieldValues));
|
||||||
|
|
||||||
iotTdEngineService.createTable(tableDto);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.tdengine;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的数据写入 Service 接口
|
||||||
|
*/
|
||||||
|
public interface TdEngineDataWriterService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入数据 - 指定列插入数据
|
||||||
|
*
|
||||||
|
* @param table 数据
|
||||||
|
* dataBaseName 数据库名
|
||||||
|
* tableName 表名
|
||||||
|
* columns 列
|
||||||
|
*/
|
||||||
|
void insertData(TdTableDO table);
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.tdengine;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDataWriterMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的数据写入 Service 实现类
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class TdEngineDataWriterServiceImpl implements TdEngineDataWriterService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TdEngineDataWriterMapper tdEngineDataWriterMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void insertData(TdTableDO table) {
|
||||||
|
tdEngineDataWriterMapper.insertData(table);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.tdengine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的数据库 Service 接口
|
||||||
|
*/
|
||||||
|
public interface TdEngineDatabaseService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建数据库
|
||||||
|
*
|
||||||
|
* @param dataBaseName 数据库名称
|
||||||
|
*/
|
||||||
|
void createDatabase(String dataBaseName);
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.tdengine;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDatabaseMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的数据库 Service 实现类
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class TdEngineDatabaseServiceImpl implements TdEngineDatabaseService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TdEngineDatabaseMapper tdEngineDatabaseMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createDatabase(String dataBaseName) {
|
||||||
|
tdEngineDatabaseMapper.createDatabase(dataBaseName);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.tdengine;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的查询 Service 接口
|
||||||
|
*/
|
||||||
|
public interface TdEngineQueryService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取历史数据
|
||||||
|
*
|
||||||
|
* @param selectVisualDO 查询条件
|
||||||
|
* @return 历史数据列表
|
||||||
|
*/
|
||||||
|
List<Map<String, Object>> getHistoryData(SelectVisualDO selectVisualDO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取历史数据条数
|
||||||
|
*
|
||||||
|
* @param selectVisualDO 查询条件
|
||||||
|
* @return 数据条数
|
||||||
|
*/
|
||||||
|
Long getHistoryCount(SelectVisualDO selectVisualDO);
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.tdengine;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineQueryMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TdEngineQueryServiceImpl implements TdEngineQueryService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TdEngineQueryMapper tdEngineQueryMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Map<String, Object>> getHistoryData(SelectVisualDO selectVisualDO) {
|
||||||
|
return tdEngineQueryMapper.getHistoryData(selectVisualDO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getHistoryCount(SelectVisualDO selectVisualDO) {
|
||||||
|
return tdEngineQueryMapper.getHistoryCount(selectVisualDO);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.tdengine;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的超级表 Service 接口
|
||||||
|
*/
|
||||||
|
public interface TdEngineSuperTableService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建超级表
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* columns 列信息
|
||||||
|
* tags 标签信息
|
||||||
|
*/
|
||||||
|
void createSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看超级表 - 显示当前数据库下的所有超级表信息
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
*/
|
||||||
|
|
||||||
|
List<Map<String, Object>> showSuperTables(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看超级表 - 获取超级表的结构信息
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
*/
|
||||||
|
List<Map<String, Object>> describeSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改超级表 - 增加列
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* column 列信息
|
||||||
|
*/
|
||||||
|
void addColumnForSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改超级表 - 删除列
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* column 列信息
|
||||||
|
*/
|
||||||
|
void dropColumnForSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改超级表 - 修改列宽
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* column 列信息
|
||||||
|
*/
|
||||||
|
void modifyColumnWidthForSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改超级表 - 为超级表添加标签
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* tag 标签信息
|
||||||
|
*/
|
||||||
|
void addTagForSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改超级表 - 为超级表删除标签
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* tag 标签信息
|
||||||
|
*/
|
||||||
|
void dropTagForSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查超级表是否存在
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* @return 超级表数量
|
||||||
|
*/
|
||||||
|
Integer checkSuperTableExists(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为超级表添加列
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* columns 列信息
|
||||||
|
*/
|
||||||
|
void addColumnsForSuperTable(TdTableDO superTable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为超级表删除列
|
||||||
|
*
|
||||||
|
* @param superTable 超级表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* columns 列信息
|
||||||
|
*/
|
||||||
|
void dropColumnsForSuperTable(TdTableDO superTable);
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.tdengine;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineSuperTableMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的超级表 Service 实现类
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class TdEngineSuperTableServiceImpl implements TdEngineSuperTableService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TdEngineSuperTableMapper tdEngineSuperTableMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createSuperTable(TdTableDO superTable) {
|
||||||
|
tdEngineSuperTableMapper.createSuperTable(superTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Map<String, Object>> showSuperTables(TdTableDO superTable) {
|
||||||
|
return tdEngineSuperTableMapper.showSuperTables(superTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Map<String, Object>> describeSuperTable(TdTableDO superTable) {
|
||||||
|
return tdEngineSuperTableMapper.describeSuperTable(superTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addColumnForSuperTable(TdTableDO superTable) {
|
||||||
|
tdEngineSuperTableMapper.addColumnForSuperTable(superTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dropColumnForSuperTable(TdTableDO superTable) {
|
||||||
|
tdEngineSuperTableMapper.dropColumnForSuperTable(superTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void modifyColumnWidthForSuperTable(TdTableDO superTable) {
|
||||||
|
tdEngineSuperTableMapper.modifyColumnWidthForSuperTable(superTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTagForSuperTable(TdTableDO superTable) {
|
||||||
|
tdEngineSuperTableMapper.addTagForSuperTable(superTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dropTagForSuperTable(TdTableDO superTable) {
|
||||||
|
tdEngineSuperTableMapper.dropTagForSuperTable(superTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer checkSuperTableExists(TdTableDO superTable) {
|
||||||
|
List<Map<String, Object>> results = tdEngineSuperTableMapper.showSuperTables(superTable);
|
||||||
|
return results == null || results.isEmpty() ? 0 : results.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addColumnsForSuperTable(TdTableDO superTable) {
|
||||||
|
for (TdFieldDO column : superTable.getColumns()) {
|
||||||
|
tdEngineSuperTableMapper.addColumnForSuperTable(TdTableDO.builder()
|
||||||
|
.dataBaseName(superTable.getDataBaseName())
|
||||||
|
.superTableName(superTable.getSuperTableName())
|
||||||
|
.column(column)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dropColumnsForSuperTable(TdTableDO superTable) {
|
||||||
|
for (TdFieldDO column : superTable.getColumns()) {
|
||||||
|
tdEngineSuperTableMapper.dropColumnForSuperTable(TdTableDO.builder()
|
||||||
|
.dataBaseName(superTable.getDataBaseName())
|
||||||
|
.superTableName(superTable.getSuperTableName())
|
||||||
|
.column(column)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.tdengine;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的表 Service 接口
|
||||||
|
*/
|
||||||
|
public interface TdEngineTableService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建表 - 创建超级表的子表
|
||||||
|
*
|
||||||
|
* @param table 表信息
|
||||||
|
* dataBaseName 数据库名称
|
||||||
|
* superTableName 超级表名称
|
||||||
|
* tableName 子表名称
|
||||||
|
* tags TAG 字段
|
||||||
|
*/
|
||||||
|
void createTable(TdTableDO table);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package cn.iocoder.yudao.module.iot.service.tdengine;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineTableMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TD 引擎的表 Service 实现类
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class TdEngineTableServiceImpl implements TdEngineTableService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private TdEngineTableMapper tdEngineTableMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createTable(TdTableDO table) {
|
||||||
|
tdEngineTableMapper.createTable(table);
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,7 @@ import cn.iocoder.yudao.module.iot.enums.product.IotAccessModeEnum;
|
|||||||
import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
|
import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
|
||||||
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.product.IotProductService;
|
import cn.iocoder.yudao.module.iot.service.product.IotProductService;
|
||||||
import cn.iocoder.yudao.module.iot.service.tdengine.IotDbStructureDataService;
|
import cn.iocoder.yudao.module.iot.service.tdengine.IotSuperTableService;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -52,7 +52,7 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
|
|||||||
@Resource
|
@Resource
|
||||||
private IotProductService productService;
|
private IotProductService productService;
|
||||||
@Resource
|
@Resource
|
||||||
private IotDbStructureDataService dbStructureDataService;
|
private IotSuperTableService dbStructureDataService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
|
<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDataWriterMapper">
|
||||||
|
|
||||||
|
<!-- 插入数据 -->
|
||||||
|
<insert id="insertData">
|
||||||
|
INSERT INTO ${dataBaseName}.${tableName}
|
||||||
|
<foreach item="item" collection="columns" separator=","
|
||||||
|
open="(" close=")">
|
||||||
|
${item.fieldName}
|
||||||
|
</foreach>
|
||||||
|
VALUES
|
||||||
|
<foreach item="item" collection="columns" separator=","
|
||||||
|
open="(" close=")">
|
||||||
|
#{item.fieldValue}
|
||||||
|
</foreach>
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
</mapper>
|
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
|
<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDatabaseMapper">
|
||||||
|
|
||||||
|
<!-- 创建数据库 -->
|
||||||
|
<update id="createDatabase" parameterType="String">
|
||||||
|
CREATE DATABASE IF NOT EXISTS ${dataBaseName}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
</mapper>
|
@ -1,327 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
||||||
|
|
||||||
<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper">
|
|
||||||
<!-- TODO 对 $ 符号有安全要求的话,后期改为接口方式 -->
|
|
||||||
|
|
||||||
<update id="createDatabase" parameterType="String">
|
|
||||||
CREATE DATABASE IF NOT EXISTS ${dataBaseName}
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<update id="createSuperTable">
|
|
||||||
CREATE STABLE IF NOT EXISTS ${dataBaseName}.${superTableName}
|
|
||||||
<foreach item="item" collection="schemaFields" separator=","
|
|
||||||
open="(" close=")" index="">
|
|
||||||
<if test="item.fieldName != null || item.fieldName != ''">
|
|
||||||
${item.fieldName}
|
|
||||||
</if>
|
|
||||||
<if test="item.dataType != null || item.dataType != ''">
|
|
||||||
<choose>
|
|
||||||
<when test="item.dataType == 'TIMESTAMP'">
|
|
||||||
TIMESTAMP
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'TINYINT'">
|
|
||||||
TINYINT
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'SMALLINT'">
|
|
||||||
SMALLINT
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'INT'">
|
|
||||||
INT
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'BIGINT'">
|
|
||||||
BIGINT
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'FLOAT'">
|
|
||||||
FLOAT
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'DOUBLE'">
|
|
||||||
DOUBLE
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'BINARY'">
|
|
||||||
BINARY
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'NCHAR'">
|
|
||||||
NCHAR
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'BOOL'">
|
|
||||||
BOOL
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'JSON'">
|
|
||||||
JSON
|
|
||||||
</when>
|
|
||||||
</choose>
|
|
||||||
</if>
|
|
||||||
<if test="item.dataLength > 0">
|
|
||||||
(
|
|
||||||
${item.dataLength}
|
|
||||||
)
|
|
||||||
</if>
|
|
||||||
</foreach>
|
|
||||||
TAGS
|
|
||||||
<!--tdEngine不支持动态tags里的数据类型,只能使用choose标签比对-->
|
|
||||||
<foreach item="item" collection="tagsFields" separator=","
|
|
||||||
open="(" close=")" index="">
|
|
||||||
<if test="item.fieldName != null || item.fieldName != ''">
|
|
||||||
${item.fieldName}
|
|
||||||
</if>
|
|
||||||
<if test="item.dataType != null || item.dataType != ''">
|
|
||||||
<choose>
|
|
||||||
<when test="item.dataType == 'TIMESTAMP'">
|
|
||||||
TIMESTAMP
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'TINYINT'">
|
|
||||||
TINYINT
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'SMALLINT'">
|
|
||||||
SMALLINT
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'INT'">
|
|
||||||
INT
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'BIGINT'">
|
|
||||||
BIGINT
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'FLOAT'">
|
|
||||||
FLOAT
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'DOUBLE'">
|
|
||||||
DOUBLE
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'BINARY'">
|
|
||||||
BINARY
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'NCHAR'">
|
|
||||||
NCHAR
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'BOOL'">
|
|
||||||
BOOL
|
|
||||||
</when>
|
|
||||||
<when test="item.dataType == 'JSON'">
|
|
||||||
JSON
|
|
||||||
</when>
|
|
||||||
</choose>
|
|
||||||
</if>
|
|
||||||
<if test="item.dataLength > 0">
|
|
||||||
(
|
|
||||||
${item.dataLength}
|
|
||||||
)
|
|
||||||
</if>
|
|
||||||
</foreach>
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<!-- CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...);-->
|
|
||||||
<update id="createTable">
|
|
||||||
CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName}
|
|
||||||
USING ${dataBaseName}.${superTableName}
|
|
||||||
<foreach item="item" collection="tagsFieldValues" separator="," open="(" close=")">
|
|
||||||
${item.fieldName}
|
|
||||||
</foreach>
|
|
||||||
TAGS
|
|
||||||
<foreach item="item" collection="tagsFieldValues" separator="," open="(" close=")">
|
|
||||||
#{item.fieldValue}
|
|
||||||
</foreach>
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<!-- insert into d1004 (ts, voltage, phase) values("2018-10-04 14:38:06", 223, 0.29) -->
|
|
||||||
<insert id="insertData">
|
|
||||||
INSERT INTO ${dataBaseName}.${tableName}
|
|
||||||
<foreach item="item" collection="schemaFieldValues" separator=","
|
|
||||||
open="(" close=")" index="">
|
|
||||||
${item.fieldName}
|
|
||||||
</foreach>
|
|
||||||
VALUES
|
|
||||||
<foreach item="item" collection="schemaFieldValues" separator=","
|
|
||||||
open="(" close=")" index="">
|
|
||||||
#{item.fieldValue}
|
|
||||||
</foreach>
|
|
||||||
</insert>
|
|
||||||
|
|
||||||
<select id="selectByTimestamp" parameterType="cn.iocoder.yudao.module.iot.domain.SelectDto"
|
|
||||||
resultType="Map">
|
|
||||||
select * from #{dataBaseName}.#{tableName}
|
|
||||||
<!--查询这里不能使用#{}占位符的方式,使用这种方式,tdEngine不识别为列名,只能使用${}占位的方式-->
|
|
||||||
<!--因为tdEngine引擎一次只执行一条sql,所以有效预防了sql的注入,且该服务该接口为内部调用,所以可以使用${}-->
|
|
||||||
where ${fieldName}
|
|
||||||
between #{startTime} and #{endTime}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<update id="addColumnForSuperTable">
|
|
||||||
ALTER STABLE ${dataBaseName}.${superTableName} ADD COLUMN
|
|
||||||
<if test="field.fieldName != null || field.fieldName != ''">
|
|
||||||
#{field.fieldName}
|
|
||||||
</if>
|
|
||||||
<if test="field.dataType != null || field.dataType != ''">
|
|
||||||
<choose>
|
|
||||||
<when test="field.dataType == 'TIMESTAMP'">
|
|
||||||
TIMESTAMP
|
|
||||||
</when>
|
|
||||||
<when test="field.dataType == 'TINYINT'">
|
|
||||||
TINYINT
|
|
||||||
</when>
|
|
||||||
<when test="field.dataType == 'SMALLINT'">
|
|
||||||
SMALLINT
|
|
||||||
</when>
|
|
||||||
<when test="field.dataType == 'INT'">
|
|
||||||
INT
|
|
||||||
</when>
|
|
||||||
<when test="field.dataType == 'BIGINT'">
|
|
||||||
BIGINT
|
|
||||||
</when>
|
|
||||||
<when test="field.dataType == 'FLOAT'">
|
|
||||||
FLOAT
|
|
||||||
</when>
|
|
||||||
<when test="field.dataType == 'DOUBLE'">
|
|
||||||
DOUBLE
|
|
||||||
</when>
|
|
||||||
<when test="field.dataType == 'BINARY'">
|
|
||||||
BINARY
|
|
||||||
</when>
|
|
||||||
<when test="field.dataType == 'NCHAR'">
|
|
||||||
NCHAR
|
|
||||||
</when>
|
|
||||||
<when test="field.dataType == 'BOOL'">
|
|
||||||
BOOL
|
|
||||||
</when>
|
|
||||||
<when test="field.dataType == 'JSON'">
|
|
||||||
JSON
|
|
||||||
</when>
|
|
||||||
</choose>
|
|
||||||
</if>
|
|
||||||
<if test="field.dataLength > 0">
|
|
||||||
(
|
|
||||||
#{field.dataLength}
|
|
||||||
)
|
|
||||||
</if>
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<update id="dropColumnForSuperTable">
|
|
||||||
ALTER STABLE ${dataBaseName}.${superTableName} DROP COLUMN
|
|
||||||
<if test="field.fieldName != null || field.fieldName != ''">
|
|
||||||
#{field.fieldName}
|
|
||||||
</if>
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<update id="addTagForSuperTable">
|
|
||||||
ALTER
|
|
||||||
STABLE
|
|
||||||
#{superTableName}
|
|
||||||
ADD
|
|
||||||
TAG
|
|
||||||
<if test="field.fieldName != null || fieldDO.fieldName != ''">
|
|
||||||
#{fieldDO.fieldName}
|
|
||||||
</if>
|
|
||||||
<if test="fieldDO.dataType != null || fieldDO.dataType != ''">
|
|
||||||
<choose>
|
|
||||||
<when test="fieldDO.dataType == 'timestamp'">
|
|
||||||
timestamp
|
|
||||||
</when>
|
|
||||||
<when test="fieldDO.dataType == 'tinyint'">
|
|
||||||
tinyint
|
|
||||||
</when>
|
|
||||||
<when test="fieldDO.dataType == 'smallint'">
|
|
||||||
smallint
|
|
||||||
</when>
|
|
||||||
<when test="fieldDO.dataType == 'int'">
|
|
||||||
int
|
|
||||||
</when>
|
|
||||||
<when test="fieldDO.dataType == 'bigint'">
|
|
||||||
bigint
|
|
||||||
</when>
|
|
||||||
<when test="fieldDO.dataType == 'float'">
|
|
||||||
float
|
|
||||||
</when>
|
|
||||||
<when test="fieldDO.dataType == 'double'">
|
|
||||||
double
|
|
||||||
</when>
|
|
||||||
<when test="fieldDO.dataType == 'binary'">
|
|
||||||
binary
|
|
||||||
</when>
|
|
||||||
<when test="fieldDO.dataType == 'nchar'">
|
|
||||||
nchar
|
|
||||||
</when>
|
|
||||||
<when test="fieldDO.dataType == 'bool'">
|
|
||||||
bool
|
|
||||||
</when>
|
|
||||||
<when test="fieldDO.dataType == 'json'">
|
|
||||||
json
|
|
||||||
</when>
|
|
||||||
</choose>
|
|
||||||
</if>
|
|
||||||
<if test="fieldDO.dataLength > 0">
|
|
||||||
(
|
|
||||||
#{fieldDO.dataLength}
|
|
||||||
)
|
|
||||||
</if>
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<update id="dropTagForSuperTable">
|
|
||||||
ALTER
|
|
||||||
STABLE
|
|
||||||
#{superTableName}
|
|
||||||
DROP
|
|
||||||
TAG
|
|
||||||
<if test="fieldsVo.fieldName != null || fieldsVo.fieldName != ''">
|
|
||||||
#{fieldsVo.fieldName}
|
|
||||||
</if>
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<select id="getCountByTimestamp" parameterType="cn.iocoder.yudao.module.iot.domain.SelectDto"
|
|
||||||
resultType="java.util.Map">
|
|
||||||
SELECT count(0) AS count
|
|
||||||
FROM #{dataBaseName}.#{tableName}
|
|
||||||
WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="showSuperTables" resultType="java.util.Map">
|
|
||||||
SHOW ${dataBaseName}.STABLES LIKE '${superTableName}'
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="getLastData" resultType="java.util.Map">
|
|
||||||
select last(time), *
|
|
||||||
from #{tableName}
|
|
||||||
where device_id = #{deviceId}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="getLastDataByTags" parameterType="cn.iocoder.yudao.module.iot.domain.TagsSelectDao"
|
|
||||||
resultType="Map">
|
|
||||||
select last(*)
|
|
||||||
from #{dataBaseName}.#{stableName}
|
|
||||||
group by ${tagsName}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="getHistoryData" resultType="java.util.Map"
|
|
||||||
parameterType="cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto">
|
|
||||||
SELECT ${fieldName} as data, time
|
|
||||||
FROM ${dataBaseName}.${tableName}
|
|
||||||
WHERE time BETWEEN #{startTime} AND #{endTime}
|
|
||||||
AND ${fieldName} IS NOT NULL
|
|
||||||
ORDER BY time DESC
|
|
||||||
LIMIT #{params.rows} offset #{params.page}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="getRealtimeData" resultType="java.util.Map"
|
|
||||||
parameterType="cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto">
|
|
||||||
SELECT #{fieldName}, time
|
|
||||||
FROM #{dataBaseName}.#{tableName}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="getAggregateData" resultType="java.util.Map"
|
|
||||||
parameterType="cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto">
|
|
||||||
SELECT #{aggregate}(${fieldName})
|
|
||||||
FROM #{dataBaseName}.#{tableName}
|
|
||||||
WHERE ts BETWEEN #{startTime} AND #{endTime} interval (${interval})
|
|
||||||
LIMIT #{num}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="describeSuperTable" resultType="java.util.Map">
|
|
||||||
DESCRIBE ${dataBaseName}.${superTableName}
|
|
||||||
</select>
|
|
||||||
<select id="getHistoryCount" resultType="java.lang.Long">
|
|
||||||
SELECT count(time)
|
|
||||||
FROM ${dataBaseName}.${tableName}
|
|
||||||
WHERE time BETWEEN #{startTime} AND #{endTime}
|
|
||||||
AND ${fieldName} IS NOT NULL
|
|
||||||
</select>
|
|
||||||
|
|
||||||
</mapper>
|
|
@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
|
<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineQueryMapper">
|
||||||
|
|
||||||
|
<!-- 根据时间戳查询数据 -->
|
||||||
|
<select id="selectByTimestamp" parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO"
|
||||||
|
resultType="Map">
|
||||||
|
SELECT * FROM ${dataBaseName}.${tableName}
|
||||||
|
WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取时间范围内的数据条数 -->
|
||||||
|
<select id="getCountByTimestamp" parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO"
|
||||||
|
resultType="java.util.Map">
|
||||||
|
SELECT COUNT(0) AS count
|
||||||
|
FROM ${dataBaseName}.${tableName}
|
||||||
|
WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取最新数据 -->
|
||||||
|
<select id="getLastData" resultType="java.util.Map">
|
||||||
|
SELECT LAST(time), *
|
||||||
|
FROM ${tableName}
|
||||||
|
WHERE device_id = #{deviceId}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 根据标签获取最新数据 -->
|
||||||
|
<select id="getLastDataByTags" parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO"
|
||||||
|
resultType="Map">
|
||||||
|
SELECT LAST(*)
|
||||||
|
FROM ${dataBaseName}.${stableName}
|
||||||
|
GROUP BY ${tagsName}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取历史数据 -->
|
||||||
|
<select id="getHistoryData" resultType="java.util.Map"
|
||||||
|
parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO">
|
||||||
|
SELECT ${fieldName} AS data, time
|
||||||
|
FROM ${dataBaseName}.${tableName}
|
||||||
|
WHERE time BETWEEN #{startTime} AND #{endTime}
|
||||||
|
AND ${fieldName} IS NOT NULL
|
||||||
|
ORDER BY time DESC
|
||||||
|
LIMIT #{params.rows} OFFSET #{params.page}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取实时数据 -->
|
||||||
|
<select id="getRealtimeData" resultType="java.util.Map"
|
||||||
|
parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO">
|
||||||
|
SELECT ${fieldName}, time
|
||||||
|
FROM ${dataBaseName}.${tableName}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取聚合数据 -->
|
||||||
|
<select id="getAggregateData" resultType="java.util.Map"
|
||||||
|
parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO">
|
||||||
|
SELECT ${aggregate}(${fieldName})
|
||||||
|
FROM ${dataBaseName}.${tableName}
|
||||||
|
WHERE ts BETWEEN #{startTime} AND #{endTime} INTERVAL (${interval})
|
||||||
|
LIMIT #{num}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取历史数据条数 -->
|
||||||
|
<select id="getHistoryCount" resultType="java.lang.Long">
|
||||||
|
SELECT COUNT(time)
|
||||||
|
FROM ${dataBaseName}.${tableName}
|
||||||
|
WHERE time BETWEEN #{startTime} AND #{endTime}
|
||||||
|
AND ${fieldName} IS NOT NULL
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
@ -0,0 +1,72 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
|
<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineSuperTableMapper">
|
||||||
|
|
||||||
|
<!-- 创建超级表 -->
|
||||||
|
<update id="createSuperTable">
|
||||||
|
CREATE STABLE IF NOT EXISTS ${dataBaseName}.${superTableName}
|
||||||
|
<foreach item="item" collection="columns" separator=","
|
||||||
|
open="(" close=")">
|
||||||
|
${item.fieldName} ${item.dataType}
|
||||||
|
<if test="item.dataLength > 0">
|
||||||
|
(${item.dataLength})
|
||||||
|
</if>
|
||||||
|
</foreach>
|
||||||
|
TAGS
|
||||||
|
<foreach item="item" collection="tags" separator=","
|
||||||
|
open="(" close=")">
|
||||||
|
${item.fieldName} ${item.dataType}
|
||||||
|
<if test="item.dataLength > 0">
|
||||||
|
(${item.dataLength})
|
||||||
|
</if>
|
||||||
|
</foreach>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 查看超级表 -->
|
||||||
|
<select id="showSuperTables" resultType="java.util.Map">
|
||||||
|
SHOW ${dataBaseName}.STABLES LIKE '${superTableName}'
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 描述超级表结构 -->
|
||||||
|
<select id="describeSuperTable" resultType="java.util.Map">
|
||||||
|
DESCRIBE ${dataBaseName}.${superTableName}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 为超级表添加列 -->
|
||||||
|
<update id="addColumnForSuperTable">
|
||||||
|
ALTER STABLE ${dataBaseName}.${superTableName} ADD COLUMN ${column.fieldName} ${column.dataType}
|
||||||
|
<if test="column.dataLength > 0">
|
||||||
|
(${column.dataLength})
|
||||||
|
</if>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 为超级表删除列 -->
|
||||||
|
<update id="dropColumnForSuperTable">
|
||||||
|
ALTER STABLE ${dataBaseName}.${superTableName} DROP COLUMN ${column.fieldName}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 修改列宽 -->
|
||||||
|
<update id="modifyColumnWidthForSuperTable">
|
||||||
|
ALTER STABLE ${dataBaseName}.${superTableName} MODIFY COLUMN ${column.fieldName} ${column.dataType}
|
||||||
|
<if test="column.dataLength > 0">
|
||||||
|
(${column.dataLength})
|
||||||
|
</if>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 为超级表添加标签 -->
|
||||||
|
<update id="addTagForSuperTable">
|
||||||
|
ALTER STABLE ${dataBaseName}.${superTableName} ADD TAG ${tag.fieldName} ${tag.dataType}
|
||||||
|
<if test="tag.dataLength > 0">
|
||||||
|
(${tag.dataLength})
|
||||||
|
</if>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 为超级表删除标签 -->
|
||||||
|
<update id="dropTagForSuperTable">
|
||||||
|
ALTER STABLE ${dataBaseName}.${superTableName} DROP TAG ${tag.fieldName}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
</mapper>
|
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
|
<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineTableMapper">
|
||||||
|
|
||||||
|
<!-- 创建子表 -->
|
||||||
|
<update id="createTable">
|
||||||
|
CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName}
|
||||||
|
USING ${dataBaseName}.${superTableName}
|
||||||
|
TAGS
|
||||||
|
<foreach item="item" collection="tags" separator=","
|
||||||
|
open="(" close=")">
|
||||||
|
#{item.fieldValue}
|
||||||
|
</foreach>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<!-- 创建子表,带有 TAGS -->
|
||||||
|
<update id="createTableWithTags">
|
||||||
|
CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName}
|
||||||
|
USING ${dataBaseName}.${superTableName}
|
||||||
|
<foreach item="item" collection="tags" separator="," open="(" close=")">
|
||||||
|
#{item.fieldName}
|
||||||
|
</foreach>
|
||||||
|
TAGS
|
||||||
|
<foreach item="item" collection="tags" separator=","
|
||||||
|
open="(" close=")">
|
||||||
|
#{item.fieldValue}
|
||||||
|
</foreach>
|
||||||
|
</update>
|
||||||
|
|
||||||
|
</mapper>
|
Loading…
x
Reference in New Issue
Block a user