MybatisPlus实现Tdengine增删改查功能

news2025/1/7 14:33:11

MybatisPlus实现Tdengine增删改查功能

1 增加pom
  <!-- https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver -->
        <dependency>
            <groupId>com.taosdata.jdbc</groupId>
            <artifactId>taos-jdbcdriver</artifactId>
            <version>3.1.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.codehaus.groovy</groupId>
                    <artifactId>groovy</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
 
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>4.2.0</version>
        </dependency>


2 配置信息
spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        master:
         # url: jdbc:mysql://20.6.1.241:3306/shine_industry?characterEncoding=utf-8&useSSL=false&keepAlive=true&autoReconnect=true&autoReconnectForPools=true&connectTimeout=30000&socketTimeout=60000
          url: jdbc:mysql://127.0.0.1:3306/shine_test_db?characterEncoding=utf-8&useSSL=false&keepAlive=true&autoReconnect=true&autoReconnectForPools=true&connectTimeout=30000&socketTimeout=60000
          username: root
          password: 123456

          driver-class-name: com.mysql.cj.jdbc.Driver
          druid:
            initial-size: 5                                       # 初始化大小
            minIdle: 10                                          # 最小连接数
            maxActive: 20                                        # 最大连接数
            max-wait: 60000                                       # 获取连接时的最大等待时间
            min-evictable-idle-time-millis: 300000                # 一个连接在池中最小生存的时间,单位是毫秒
            time-between-eviction-runs-millis: 60000              # 多久才进行一次检测需要关闭的空闲连接,单位是毫秒
            filters: stat                                         # 配置扩展插件:stat-监控统计,log4j-日志,wall-防火墙(防止SQL注入),去掉后,监控界面的sql无法统计   ,wall
            validation-query: SELECT 1                            # 检测连接是否有效的 SQL语句,为空时以下三个配置均无效
            test-on-borrow: true                                  # 申请连接时执行validationQuery检测连接是否有效,默认true,开启后会降低性能
            test-on-return: false                                  # 归还连接时执行validationQuery检测连接是否有效,默认false,开启后会降低性能
            test-while-idle: true                                 # 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效,默认false,建议开启,不影响性能
            maxPoolPreparedStatementPerConnectionSize: 50
            keep-alive: false

        ng:
          driver-class-name: com.taosdata.jdbc.rs.RestfulDriver
          url: jdbc:TAOS-RS://127.0.0.1:6041?useSSL=false&user=root&password=taosdata
          # using connection pools
          type: com.alibaba.druid.pool.DruidDataSource
          druid:
            initial-size: 5
            min-idle: 5
            max-active: 20
            max-wait: 60000
            time-between-eviction-runs-millis: 60000
            min-evictable-idle-time-millis: 300000
            validation-query: SELECT 1
            pool-prepared-statements: true
            max-pool-prepared-statement-per-connection-size: 20
    druid:
      connect-timeout: 300
      maxPoolPreparedStatementPerConnectionSize: 100
      initialSize: 10                                       # 初始化大小
      minIdle: 5                                          # 最小连接数
      maxActive: 20                                        # 最大连接数
      max-wait: 60000                                       # 获取连接时的最大等待时间
      min-evictable-idle-time-millis: 300000                # 一个连接在池中最小生存的时间,单位是毫秒
      time-between-eviction-runs-millis: 60000              # 多久才进行一次检测需要关闭的空闲连接,单位是毫秒
      filters: stat                                         # 配置扩展插件:stat-监控统计,log4j-日志,wall-防火墙(防止SQL注入),去掉后,监控界面的sql无法统计   ,wall
      validation-query: SELECT 1                            # 检测连接是否有效的 SQL语句,为空时以下三个配置均无效
      test-on-borrow: false                                  # 申请连接时执行validationQuery检测连接是否有效,默认true,开启后会降低性能
      test-on-return: false                                  # 归还连接时执行validationQuery检测连接是否有效,默认false,开启后会降低性能
      test-while-idle: true                                 # 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效,默认false,建议开启,不影响性能
      stat-view-servlet:                                    # http://127.0.0.1:8088/druid/
        enabled: true                                       # 是否开启 StatViewServlet
        allow: 127.0.0.1                                    # 访问监控页面 白名单,默认127.0.0.1
        deny: 192.168.56.1                                  # 访问监控页面 黑名单
        login-username: admin                               # 访问监控页面 登陆账号
        login-password: admin                             # 访问监控页面 登陆密码
        url-pattern: /druid/*
      filter:
        stat:
          enabled: true                                     # 是否开启 FilterStat,默认true
          log-slow-sql: true                                # 是否开启 慢SQL 记录,默认false
          slow-sql-millis: 5000                             # 慢 SQL 的标准,默认 3000,单位:毫秒
          merge-sql: false                                  # 合并多个连接池的监控数据,默认false
      keep-alive: true
3 实现Model

创建自己实体,然后集成baseModel


import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.StringUtils;
import org.springframework.format.annotation.DateTimeFormat;

import java.sql.Timestamp;
import java.time.LocalDateTime;

/**
 * taos基础类
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class BaseTdModel<T extends Model<T>> extends Model<T> implements TdBaseInterface {

    private static final long serialVersionUID = 2537647301574172972L;

    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty("时间戳")
    private Timestamp ts;

    @JsonIgnore
    @TableField(exist = false)
    @ApiModelProperty("数据库名")
    private String databaseName;

    @JsonIgnore
    @TableField(exist = false)
    @ApiModelProperty("超级表名")
    private String stableName;

    @JsonIgnore
    @TableField(exist = false)
    @ApiModelProperty("表名")
    private String tableName;

    @JsonIgnore
    @TableField(exist = false)
    @ApiModelProperty("insertValue相关语句")
    private String insertValue;

    @JsonIgnore
    @TableField(exist = false)
    @ApiModelProperty("insertTag相关语句")
    private String insertTag;

    @JsonIgnore
    @TableField(exist = false)
    @ApiModelProperty("建表相关语句")
    private String createValues;

    @JsonIgnore
    @TableField(exist = false)
    @ApiModelProperty("批量新增语句")
    private String batchSql;

    /**
     * 时间戳构造方法
     *
     * @param ts 时间戳
     */
    public void setTs(Timestamp ts) {
        this.ts = ts;
    }

    /**
     * 时间戳构造方法
     *
     * @param ts 时间戳
     */
    public void setTs(Long ts) {
        this.ts = new Timestamp(ts);
    }

    /**
     * 时间戳构造方法
     *
     * @param ts 时间戳
     */
    public void setTs(LocalDateTime ts) {
        this.ts = Timestamp.valueOf(ts);
    }

    /**
     * 获取时间戳
     *
     * @return 时间戳
     */
    public Long getTsLong() {
        if (ObjectUtils.isNotEmpty(ts)) {
            return ts.getTime();
        }
        return null;
    }

    /**
     * 获取时间戳
     *
     * @return 时间戳
     */
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    public LocalDateTime getTsLocalDateTime() {
        if (ObjectUtils.isNotEmpty(ts)) {
            return ts.toLocalDateTime();
        }
        return null;
    }

    /**
     * 初始化相关语句方法
     *
     * @param baseTaosModel taos基础实体类
     */
    public void init(BaseTdModel<?> baseTaosModel) {
        // 如果时间戳为空,默认当前时间
        if (ObjectUtils.isEmpty(this.ts)) {
            this.ts = new Timestamp(System.currentTimeMillis());
        }
        // 如果数据库或超级表为空,默认从@TableName获取
        if (StringUtils.isEmpty(this.stableName)) {
            this.databaseName = getTableName(baseTaosModel)[0];
        }
        if (StringUtils.isEmpty(this.stableName)) {
            this.stableName = getTableName(baseTaosModel)[1];
        }
        // 获取value和tag语句
        this.insertValue = getInsertValue(baseTaosModel);
        this.insertTag = getInsertTag(baseTaosModel);
        this.createValues = getCreateSql();
    }

    /**
     * 重写构造方法,初始化成员变量,减少taos的null值存储
     */
    public BaseTdModel() {
        setStringFieldsToEmpty(this);
    }

}

BaseTdModel 实现接口 TaosBaseInterface  

public interface TaosBaseInterface {

    default String getDatabaseName(BaseTaosModel<?> baseTaosModel){
        TableName tableName = baseTaosModel.getClass().getAnnotation(TableName.class);
        if(StringUtils.isNotBlank(tableName.value())){
            // 如果格式为DatabaseName.STableName则返回DatabaseName
            String[] split = tableName.value().split("\\.");
            if(StringUtils.isNotBlank(split[0])){
                return split[0];
            }
        }
        return null;
    }


    default String getSTableName(BaseTaosModel<?> baseTaosModel){
        TableName tableName = baseTaosModel.getClass().getAnnotation(TableName.class);
        if(StringUtils.isNotBlank(tableName.value())){
            // 如果格式为DatabaseName.STableName则返回DatabaseName
            String[] split = tableName.value().split("\\.");
            if(StringUtils.isNotBlank(split[1])){
                return split[1];
            }else {
                return tableName.value();
            }
        }
        return null;
    }


    /**
     * 根据实体类动态创建超级表语句
     * @return 建表属性语句
     */
    @JsonIgnore
    default String getCreateSql(){
        Field[] fields = this.getClass().getDeclaredFields();
        // 获取对应字段列表
        List<Field> valueFields = getTagsFields(fields, false);
        List<Field> tagFields = getTagsFields(fields, true);
        StringJoiner values = new StringJoiner(",", "(", ")");
        StringJoiner tags = new StringJoiner(",", "(", ")");
        // 添加默认时间戳属性
        values.add("ts timestamp");
        // 拼接values
        for (Field field : valueFields) {
            try {
                // 获取字段名和状态名
                String name = field.getName();
                String typeName = field.getType().getSimpleName();
                values.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name)+" "+typeName);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        // 拼接tags
        for (Field field : tagFields) {
            try {
                // 获取字段名和状态名
                String name = field.getName();
                String typeName = field.getType().getSimpleName();
                tags.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name)+" "+typeName);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        // 拼接建表属性相关语句,工具类替换优化性能 | 替换string类型为nchar(32) | 替换boolean为bool
        return StringUtils.replaceEach(values + " tags " + tags,
                new String[]{"String", "boolean", "Boolean","Long"},
                new String[]{"nchar(32)", "bool", "bool","bigint unsigned"});
    }

    /**
     * 通过反射拼接所有values
     *
     * @return values 所有taos属性value字符串
     */
    default String getInsertValue(BaseTaosModel<?> baseTaosModel) {
        return getValues(baseTaosModel,true) + " values " + getValues(baseTaosModel,false);
    }

    default String getInsertTag(BaseTaosModel<?> baseTaosModel) {
        return getTags(baseTaosModel,true) + " tags " + getTags(baseTaosModel,false);
    }

    /**
     * 通过反射拼接所有values
     *
     * @param baseTaosModel taos基础类
     * @param isColumn 返回字段还是value值(true:返回字段 | false:返回value)
     * @return values 所有taos属性value字符串
     */
    default String getValues(BaseTaosModel<?> baseTaosModel,boolean isColumn) {
        Field[] fields = this.getClass().getDeclaredFields();
        List<Field> orderedField = getTagsFields(fields, false);
        StringJoiner values = new StringJoiner(",", "(", ")");
        StringJoiner keys = new StringJoiner(",", "(", ")");
        keys.add("ts");
        values.add(Long.toString(baseTaosModel.getTs().getTime()));
        for (Field field : orderedField) {

            boolean annotationPresent = field.isAnnotationPresent(TableField.class);
            if(annotationPresent){
                //有此注解
                TableField annotation = field.getAnnotation(TableField.class);
                boolean exist = annotation.exist();
                if(!exist){
                    //无视其存在,不参与语句拼接
                    continue;
                }
            }


            try {
                // 添加字段名
                String name = field.getName();
                keys.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name));
                // 添加字段值
                field.setAccessible(true);
                Object o = field.get(baseTaosModel);
                List<String> valueList = StringUtil.change2String(o);
                values.add(valueList.get(0));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        if(isColumn){
            return keys.toString();
        }
        return values.toString();
    }

    /**
     * 通过反射拼接所有tags
     *
     * @param baseTaosModel taos基础类
     * @param isColumn 返回字段还是tags值(true:返回字段 | false:返回tags)
     * @return values 所有taos属性tags字符串
     */
    default String getTags(BaseTaosModel<?> baseTaosModel,boolean isColumn) {
        Field[] fields = this.getClass().getDeclaredFields();
        List<Field> orderedField = getTagsFields(fields, true);
        StringJoiner values = new StringJoiner(",", "(", ")");
        StringJoiner keys = new StringJoiner(",", "(", ")");
        for (Field field : orderedField) {
            try {
                // 添加字段名
                String name = field.getName();
                keys.add(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name));
                // 添加字段值
                field.setAccessible(true);
                Object o = field.get(baseTaosModel);
                List<String> valueList = StringUtil.change2String(o);
                values.add(valueList.get(0));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        if(isColumn){
            return keys.toString();
        }
        return values.toString();
    }

    /**
     * 获取values或tags对应的字段
     *
     * @param fields 反射获取的Field数组
     * @param isTags 是否时tags
     * @return 排序后Field列表
     */
    default List<Field> getTagsFields(Field[] fields, boolean isTags) {
        // 用来存放所有的属性域
        List<Field> values = new ArrayList<>();
        List<Field> tags = new ArrayList<>();
        // 判断是否是tags字段
        for (Field f : fields) {
            if (f.getAnnotation(Tags.class) != null) {
                tags.add(f);
            } else {
                values.add(f);
            }
        }
        if (isTags) {
            return tags;
        }
        return values;
    }

    default void setStringFieldsToEmpty(Object obj) {
        Field[] fields = this.getClass().getDeclaredFields();
        // tag不能为空字符串
        List<Field> tagsFields = getTagsFields(fields, false);
        for (Field field : tagsFields) {
            if (field.getType() == String.class) {
                try {
                    field.setAccessible(true);
                    field.set(obj, "");
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
4 创建service impl实现类
public interface BaseTaosService<T extends BaseTaosModel<T>> extends IService<T> {

    /**
     * 创建默认数据库
     * 重点:最好手动在taos中创建数据库 | 本方法使用于taos初始化默认创建
     *
     * @param baseTaosModel taos基础实体
     */
    void createDatabase(T baseTaosModel);

    /**
     * 创建具有过期时间的数据库
     * 重点:最好手动在taos中创建数据库 | 本方法使用于taos初始化默认创建
     *
     * @param baseTaosModel taos基础实体
     * @param duration      过期间隔时间
     * @param keep          保留数据时间
     */
    void createDatabaseDuration(T baseTaosModel, String duration, String keep);

    /**
     * 创建超级表
     * 重点:最好手动在taos中创建超级表 | 本方法使用于taos初始化默认创建
     * 重点:如需使用,请了解@TableName规则--
     * --多数据库同结构超级表请手动设置数据库
     *
     * @param baseTaosModel taos实体
     */
    void createSTable(T baseTaosModel);

    /**
     * 删除超级表
     *
     * @param baseTaosModel taos基础类
     */
    void dropSuperTable(T baseTaosModel);

    /**
     * 删除表
     *
     * @param baseTaosModel taos基础类
     */
    void dropTable(T baseTaosModel);

    /**
     * 新增数据
     *
     * @param baseTaosModel taos基础类
     * @return 影响行数
     */
    int insert(T baseTaosModel);

    /**
     * 批量新增方法
     * @param baseTaosModels taos基础实体类列表
     * @param count 批量数据上限 需自己预估 留好容错空间,默认1000行
     * @return 影响行数
     */
    int insertBatch(List<T> baseTaosModels, int count);

    /**
     * 批量新增方法
     * @param baseTaosModels taos基础实体类列表
     */
    int insertBatch(List<T> baseTaosModels);

    /**
     * 获取taos所有数据库名方法
     *
     * @return 数据库名list
     */
    List<String> showDatabases();

    /**
     * 获取实体类对应数据库下所有超级表名方法
     *
     * @param baseTaosModel taos实体
     * @return 数据库下所有超级表list
     */
    List<String> showSTables(T baseTaosModel);

    /**
     * 获取实体类对应数据库下所有表名方法
     *
     * @param baseTaosModel taos实体
     * @return 数据库下所有表list
     */
    List<String> showTables(T baseTaosModel);

    /**
     * 切换数据库
     * 重点 : 当前使用restFul连接,无法切换数据库 使用前确认连接方式
     *
     * @param baseTaosModel taos实体
     */
    void useDatabase(T baseTaosModel);

    /**
     * 创建流式计算方法
     *
     * @param streamName    流名称
     * @param streamOptions 流参数
     * @param stbName       表名
     * @param subquery      查询语句
     */
    void createStream(String streamName, String streamOptions, String stbName, String subquery);

    /**
     * 初始化流式计算
     */
    void initStream();
}



@Slf4j
@DS("tdengine")
public class BaseTaosServiceImpl<M extends BaseTaosMapper<T>, T extends BaseTaosModel<T>> extends ServiceImpl<M, T> implements BaseTaosService<T> {

    @Override
    protected Class<T> currentMapperClass() {
        return (Class<T>) this.getResolvableType().as(BaseTaosServiceImpl.class).getGeneric(0).getType();
    }

    @Override
    protected Class<T> currentModelClass() {
        return (Class<T>) this.getResolvableType().as(BaseTaosServiceImpl.class).getGeneric(1).getType();
    }

    @Override
    public void createDatabase(T baseTaosModel) {
        baseTaosModel.init(baseTaosModel);
        baseMapper.createDatabase(baseTaosModel);
    }

    @Override
    public void createDatabaseDuration(T baseTaosModel, String duration, String keep) {
        baseTaosModel.init(baseTaosModel);
        baseMapper.createDatabaseDuration(baseTaosModel, duration, keep);
    }

    @Override
    public void createSTable(T baseTaosModel) {
        baseTaosModel.init(baseTaosModel);
        baseMapper.createDatabase(baseTaosModel);
        baseMapper.createSTable(baseTaosModel);
    }

    @Override
    public void dropSuperTable(T baseTaosModel) {
        baseTaosModel.init(baseTaosModel);
        baseMapper.dropSuperTable(baseTaosModel);
    }

    @Override
    public void dropTable(T baseTaosModel) {
        baseTaosModel.init(baseTaosModel);
        baseMapper.dropTable(baseTaosModel);
    }

    @Override
    public int insert(T baseTaosModel) {
        baseTaosModel.init(baseTaosModel);
        return baseMapper.insert(baseTaosModel);
    }

    @Override
    public int insertBatch(List<T> list, int count) {
        // 默认值设为1000
        if (count == 0) {
            count = 1000;
        }
        // 根据表名转换map
        Map<String, List<T>> baseModelMap = list.stream()
                .filter(baseTaosModel -> ObjectUtils.isNotEmpty(baseTaosModel.getTableName()))
                .collect(Collectors.groupingBy(BaseTaosModel::getTableName));
        Set<String> strings = baseModelMap.keySet();
        // 不同表遍历新增
        int finalCount = count;
        strings.forEach(tableName -> {
            List<T> baseTaosModelList = baseModelMap.get(tableName);
            if (!baseTaosModelList.isEmpty()) {
                // sql字段标志位
                AtomicInteger i = new AtomicInteger(0);
                // StringJoiner无法清除字符,所以采用StringBuilder拼接空格
                StringBuilder tags = new StringBuilder();
                StringBuilder values = new StringBuilder();

                baseTaosModelList.forEach(baseTaosModel -> {
                    // 如果超过传入次数
                    if (i.get() > finalCount) {
                        String insertSql = tags.append(values).toString();
                        baseTaosModel.init(baseTaosModel);
                        baseTaosModel.setBatchSql(insertSql);
                        baseMapper.insertBatch(baseTaosModel, insertSql);
                        // i重新设施为0 | tags和values置空
                        i.set(0);
                        tags.delete(0, tags.length());
                        values.delete(0, values.length());
                    }
                    // 拼接新增语句
                    if (i.getAndIncrement() == 0) {
                        baseTaosModel.init(baseTaosModel);
                        tags.append(baseTaosModel.getInsertTag()).append(" ");
                        values.append(baseTaosModel.getInsertValue()).append(" ");
                    } else {
                        values.append(baseTaosModel.getValues(baseTaosModel, false)).append(" ");
                    }
                });
                String insertSql = tags.append(values).toString();
                T baseTaosModel = baseTaosModelList.get(0);
                baseTaosModel.init(baseTaosModel);
                baseTaosModel.setBatchSql(insertSql);
                baseMapper.insertBatch(baseTaosModel, insertSql);
            }
        });

        return 0;
    }

    @Override
    public int insertBatch(List<T> list) {
        // 根据表名转换map
        Map<String, List<T>> baseModelMap = list.stream()
                .filter(baseTaosModel -> ObjectUtils.isNotEmpty(baseTaosModel.getTableName()))
                .collect(Collectors.groupingBy(BaseTaosModel::getTableName));
        Set<String> strings = baseModelMap.keySet();
        // 不同表遍历新增
        strings.forEach(tableName -> {
            List<T> baseTaosModelList = baseModelMap.get(tableName);
            if (!baseTaosModelList.isEmpty()) {
                // sql字段标志位
                AtomicInteger i = new AtomicInteger(0);
                // 拼接字段
                StringJoiner tags = new StringJoiner(" ");
                StringJoiner values = new StringJoiner(" ");

                baseTaosModelList.forEach(baseTaosModel -> {
                    // 最大字节长度
                    int maxLength = 1000000;
                    // 预测长度
                    if (values.length() * 3 > maxLength) {
                        String insertSql = tags.merge(values).toString();
                        baseTaosModel.init(baseTaosModel);
                        baseTaosModel.setBatchSql(insertSql);
                        baseMapper.insertBatch(baseTaosModel, insertSql);
                        // i重新设施为0 | tags和values置空
                        i.set(0);
                        tags.setEmptyValue("");
                        values.setEmptyValue("");
                    }
                    // 拼接新增语句
                    if (i.getAndIncrement() == 0) {
                        baseTaosModel.init(baseTaosModel);
                        tags.add(baseTaosModel.getInsertTag());
                        values.add(baseTaosModel.getInsertValue());
                    } else {
                        values.add(baseTaosModel.getValues(baseTaosModel, false));
                    }
                });
                String insertSql = tags.merge(values).toString();
                T baseTaosModel = baseTaosModelList.get(0);
                baseTaosModel.init(baseTaosModel);
                baseTaosModel.setBatchSql(insertSql);
                baseMapper.insertBatch(baseTaosModel, insertSql);
            }
        });

        return 0;
    }

    @Override
    public List<String> showDatabases() {
        return baseMapper.showDatabases();
    }

    @Override
    public List<String> showSTables(T baseTaosModel) {
        return baseMapper.showSTables(baseTaosModel);
    }

    @Override
    public List<String> showTables(T baseTaosModel) {
        return baseMapper.showTables(baseTaosModel);
    }

    @Override
    public void useDatabase(T baseTaosModel) {
        baseMapper.useDatabase(baseTaosModel);
    }

    @Override
    public void createStream(String streamName, String streamOptions, String stbName, String subquery) {
        baseMapper.createStream(streamName, streamOptions, stbName, subquery);
    }

    @Override
    public void initStream() {
        //原始数据数据库名
        String originSource = TDengineDatabaseParamEnums.MONTH_THREE.getDatabaseName() + "." + TDengineConstants.TABLE_NUMERICAL_NAME;
        TDengineDatabaseParamEnums[] values = TDengineDatabaseParamEnums.values();
        for (TDengineDatabaseParamEnums value : values) {
            String databaseName = value.getDatabaseName();
            if (databaseName.equals(TDengineDatabaseParamEnums.MONTH_THREE.getDatabaseName())) {
                continue;
            }
            //原始数据源
            List<String> aggregateTimeList = StringUtil.getAggregateTimeByDatabaseName(databaseName);
            aggregateTimeList.forEach(aggregateTime -> {
                String streamName = TDengineConstants.STREAM_NAME_PREFIX + aggregateTime;
                String stbName = TDengineConstants.STREAM_TABLE_PREFIX + aggregateTime;
                //查询内容
                String subquery = StrUtil.format(TDengineSqlConstants.STREAM_SUBQUERY, originSource, aggregateTime);
                createStream(streamName, null, stbName, subquery);
            });
        }
    }
}
5 创建实体
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.growatt.industry.dao.model.td.BaseTdModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

/**
 * 收益超级表
 */
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Data
@TableName(value = "devicedb.income", autoResultMap = true)
public class TdIncome extends BaseTdModel<TdIncome> {
    /**
     * 
     */
    @TableField("plant_Id")
    private Integer plantId;
    /**
     * 
     */
    @TableField("sn")
    private String sn;
    /**
     * 地址
     */
    @TableField("addr")
    private Integer addr;

    @TableField("year")
    private Integer year;
    @TableField("month")
    private Integer month;
    @TableField("day")
    private Integer day;
    @TableField("hour")
    private Integer hour;
    @TableField("min")
    private Integer min;
    /**
     * 总收益
     */
    @TableField("income")
    private Double income;
    /**
     * 补贴收益(光伏补贴||储能补贴*放电量)
     */
    @TableField("sub_Income")
    private Double subIncome;
    /**
     * 放电量收益/卖电收益(馈入电网收益)
     */
    @TableField("discharge_Income")
    private Double dischargeIncome;
    /**
     * 充电量费用
     */
    @TableField("charge_Income")
    private Double chargeIncome;
    /**
     * 自发自用收益
     */
    @TableField("pv_Self_Income")
    private Double pvSelfIncome;
    /**
     * 收益类型(1:光伏,2:储能)
     */
    @TableField("income_Type")
    private Integer incomeType;
    /**
     * 时区
     */
    @TableField("timezone_value")
    private String timezoneValue;
    /**
     * 创建时间
     */
    @TableField("create_Time")
    private Long createTime;
    /**
     * 更新时间
     */
    @TableField("update_Time")
    private Long updateTime;
    @Tags
    private String location;
    @Tags
    private Integer groupid;

    public void initIncome(Integer plantId, String sn, Integer address, double pvEarn, int year, int monthValue, int dayOfMonth, int hour, int minute, Double subEarn, double pvToGridIncome, double i, double pvSelfIncome, int incomeType,Float timezone) {

        this.plantId = plantId;
        this.sn = sn;
        this.addr = address;
        this.income = pvEarn;
        this.subIncome = subEarn;
        this.year = year;
        this.month = monthValue;
        this.day = dayOfMonth;
        this.hour = hour;
        this.min = minute;
        this.dischargeIncome = pvToGridIncome;
        this.chargeIncome = i;
        this.pvSelfIncome = pvSelfIncome;
        this.incomeType = incomeType;
        this.timezoneValue = timezone.toString();
        this.createTime = System.currentTimeMillis();
        this.updateTime = System.currentTimeMillis();
        this.location = TDConstants.TD_LOCATION;
        this.groupid = TDConstants.TD_ROUPID;
        this.setTableName("income_"+sn);
    }

}

6 参考

https://github.com/Andlzz/Tdengine-demo
https://blog.csdn.net/qq_51409941/article/details/137817878?ops_request_misc=%257B%2522request%255Fid%2522%253A%25223825ce2901a80324c2af0a6212cfe49b%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=3825ce2901a80324c2af0a6212cfe49b&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-2-137817878-null-null.142v100pc_search_result_base5&utm_term=taos%E5%9F%BA%E7%A1%80%E7%B1%BB%20&spm=1018.2226.3001.4187

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2271848.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

QML自定义滑动条Slider的样式

代码展示 import QtQuick 2.9 import QtQuick.Window 2.2 import QtQuick.Controls 2.1Window {visible: truewidth: 640height: 480title: qsTr("Hello World")Slider {id: controlvalue: 0.5background: Rectangle {x: control.leftPaddingy: control.topPadding …

什么是.net framework,什么是.net core,什么是.net5~8,版本对应关系

我不知道有多少人和我一样&#xff0c;没学习过.netCore&#xff0c;想要学习&#xff0c;但是版本号太多就蒙了&#xff0c;不知道学什么了&#xff0c;这里解释下各个版本的关系 我们一般开始学习微软的时候&#xff0c;都是开始学习的.netframework&#xff0c;常用的就是4…

【2025最新计算机毕业设计】基于Spring Boot+Vue影院购票系统(高质量源码,提供文档,免费部署到本地)

作者简介&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流。✌ 主要内容&#xff1a;&#x1f31f;Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能…

matlab中高精度计算函数vpa与非厄米矩阵本征值的求解

clear;clc;close all tic %并行设置% delete(gcp(nocreate));%关闭之前的并行 cparcluster(local); c.NumWorkers50;%手动设置线程数(否则默认最大线程为12) parpool(c, c.NumWorkers); %并行设置%w1; u2.5;N30;valstozeros(2*N2,100); v10linspace(-3,3,100).;parfor jj1:leng…

Linux第101步_了解LCD屏驱动“panel-simple.c”

了解LCD屏驱动“panel-simple.c”有助于修改屏驱动。自己另外单独写屏驱动&#xff0c;这是不现实的&#xff0c;所以学会在源程序的基础上修改&#xff0c;才是最佳的学习方法&#xff0c;这就是我们学习框架的主要原因。在Limux系统中&#xff0c;主流的显示框架有两种:DRM(D…

TI毫米波雷达原始数据解析之Lane数据交换

TI毫米波雷达原始数据解析之Lane数据交换 背景Lane 定义Lane 确认确认LVDS Lane 数量的Matlab 代码数据格式参考 背景 解析使用mmWave Studio 抓取的ADC Data Lane 定义 芯片与DCA100之间的数据使用LVDS接口传输&#xff0c;使用mmWave Studio 配置过程中有一个选项是LVDS L…

2-markdown转网页页面设计 --[制作网页模板]

页面设计 将Markdown转换为网页页面设计通常涉及以下几个步骤&#xff1a; 编写Markdown内容&#xff1a; 首先&#xff0c;你需要创建或已有以Markdown格式编写的文档。Markdown是一种轻量级的标记语言&#xff0c;它允许人们使用易读易写的纯文本格式编写文档&#xff0c;然…

Linux驱动开发(18):linux驱动并发与竞态

并发是指多个执行单元同时、并行执行&#xff0c;而并发的执行单元对共享资源(硬件资源和软件上的全局变量、静态变量等)的访问 则很容易导致竞态。对于多核系统&#xff0c;很容易理解&#xff0c;由于多个CPU同时执行&#xff0c;多个CPU同时读、写共享资源时很容易造成竞态。…

Elasticsearch: 高级搜索

这里写目录标题 一、match_all匹配所有文档1、介绍&#xff1a; 二、精确匹配1、term单字段精确匹配查询2、terms多字段精确匹配3、range范围查询4、exists是否存在查询5、ids根据一组id查询6、prefix前缀匹配7、wildcard通配符匹配8、fuzzy支持编辑距离的模糊查询9、regexp正则…

GitLab集成Runner详细版--及注意事项汇总【最佳实践】

一、背景 看到网上很多用户提出的runner问题其实实际都不是问题&#xff0c;不过是因为对runner的一些细节不清楚导致了误解。本文不系统性的介绍GitLab-Runner&#xff0c;因为这类文章写得好的特别多&#xff0c;本文只汇总一些常几的问题/注意事项。旨在让新手少弯路。 二、…

Spring Boot 中 RabbitMQ 的使用

目录 引入依赖 添加配置 Simple&#xff08;简单模式&#xff09; 生产者代码 消费者代码 ​编辑 Work Queue&#xff08;工作队列&#xff09; 生产者代码 消费者代码 Publish/Subscribe&#xff08;发布/订阅&#xff09; 生产者代码 消费者代码 Routing&#x…

【linux基础I/O(1)】文件描述符的本质重定向的本质

目录 前言1. 理解C语言的文件接口2. 操作文件的系统调用接口2.1 open函数详解2.2 close函数详解2.3 write函数详解2.4 read函数详解 3. 文件描述符fd详解4. 文件描述符的内核本质5. 怎样理解Linux下一切皆文件?6. 理解输出输入重定向7. 重定向的系统调用8. 总结 前言 “在Lin…

全面解析 Node-RED:功能、Docker 部署与实战示例

言简意赅的讲解Node-RED解决的痛点 Node-RED 是一个基于流的编程工具&#xff0c;专为物联网&#xff08;IoT&#xff09;应用而设计。它通过可视化的编程界面&#xff0c;使开发者能够轻松地连接各种硬件设备、API 以及在线服务&#xff0c;构建复杂的应用流程。本文将详细介…

2、pycharm常用快捷命令和配置【持续更新中】

1、常用快捷命令 Ctrl / 行注释/取消行注释 Ctrl Alt L 代码格式化 Ctrl Alt I 自动缩进 Tab / Shift Tab 缩进、不缩进当前行 Ctrl N 跳转到类 Ctrl 鼠标点击方法 可以跳转到方法所在的类 2、使用pip命令安装request库 命令&#xff1a;pip install requests 安装好了…

2025-01-04 Unity插件 YodaSheet1 —— 插件介绍

文章目录 1 介绍2 工作原理2.1 ScriptableObject -> YadeSheetData2.2 YadeDatabase 存储多个 YadeSheetData 3 用途4 缺点5 推荐 1 介绍 ​ Yade 提供类似于 Excel 或者 Google Sheets 的表格编辑器&#xff0c;可以轻松地在 Unity 编辑器中 编辑&#xff0c;搜索&#xf…

用 C++ 创建控制台计算器

本文内容 先决条件创建应用项目验证新应用是否生成并运行编辑代码 显示另外 5 个 C 程序员通常从在命令行上运行的“Hello, world!”应用程序开始。 你将以本文为起点&#xff0c;逐步进阶&#xff0c;加深学习难度&#xff1a;计算器应用。 先决条件 在 Visual Studio 中…

IDEA 撤销 merge 操作(详解)

作为一个开发者&#xff0c;我们都知道Git是一个非常重要的版本控制工具&#xff0c;尤其是在协作开发的过程中。然而&#xff0c;在使用Git的过程中难免会踩一些坑&#xff0c;今天我来给大家分享一个我曾经遇到的问题&#xff1a;在使用IDEA中进行merge操作后如何撤销错误的合…

限时特惠,香港服务器,低至53元/年

家人们谁懂啊&#xff01;香港服务器这价格简直逆天了&#xff0c;居然比内地的还便宜&#xff01;就拿阿里云来说&#xff0c;人家最低配置的服务器&#xff0c;价格都很难做到这么亲民。 最低配的就不说了&#xff0c;2 核 4G 的配置&#xff0c;应对日常业务稳稳当当&#x…

EF Core配置及使用

Entity Framework Core是微软官方的ORM框架。 ORM&#xff1a;Object Relational Mapping。让开发者用对象操作的形式操作关系数据库。 EF Core是对于底层ADO.NET Core的封装&#xff0c;因此ADO.NET Core支持的数据库不一定被EF Core支持。 代码创建数据库Code First 建实…

GPT分区 使用parted标准分区划分,以及相邻分区扩容

parted 是一个功能强大的命令行工具&#xff0c;用于创建和管理磁盘分区表和分区。它支持多种分区表类型&#xff0c;如 MBR&#xff08;msdos&#xff09;、GPT&#xff08;GUID Partition Table&#xff09;等&#xff0c;并且可以处理大容量磁盘。parted 提供了一个交互式界…