iotdb操作工具类

package com.xinao.monitor.utils;

import com.xinao.common.core.utils.DateUtils;
import com.xinao.common.core.utils.SpringUtils;
import com.xinao.common.core.utils.StringUtils;
import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.session.pool.SessionDataSetWrapper;
import org.apache.iotdb.session.pool.SessionPool;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.read.common.RowRecord;
import org.apache.poi.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

@Component
@Configuration
public class IotDBSession {

    private static final Logger logger = LoggerFactory.getLogger(IotDBSession.class);

    @Value("${spring.iotdb.username:root}")
    private String username;
    @Value("${spring.iotdb.password:root}")
    private String password;
    @Value("${spring.iotdb.ip:192.168.88.21}")
    private String ip;
    @Value("${spring.iotdb.port: 6667}")
    private int port;
    @Value("${spring.iotdb.maxSize: 10}")
    private int maxSize;

    private static SessionPool sessionPool;

    public void getSessionPool() {
        if (sessionPool == null) {
            sessionPool = new SessionPool(ip, port, username, password, maxSize);
        }
    }

    /**
     * IOT 插入数据
     *
     * @param root 私有路径
     * @param time 时间序列
     * @param t 目标对象
     * @throws StatementExecutionException
     * @throws IoTDBConnectionException
     */
    public static <T> void insert(String root, Date time, T t, Class<T> target) throws StatementExecutionException, IoTDBConnectionException {
        SpringUtils.getBean(IotDBSession.class).getSessionPool();
        // 路径 root.xinao.设备eid.报警记录eid
        if(StringUtils.isEmpty(root) || time == null){
            throw new StatementExecutionException("私有路径或时间不为空!");
        }
        Assert.notNull(t.getClass() != target ? null : new Object(),"实体类型不匹配");
        // 指定路径 时间
        long times = time.getTime() / 1000 * 1000;
        String deviceId = root;
        // 获取测点序列
        List<Object> values = new LinkedList<>();
        List<TSDataType> types = new LinkedList<>();
        // 字段名序列
        List<String> measurements = new ArrayList<>();
        Field[] declaredFields = target.getDeclaredFields();
        if(declaredFields.length == 0){
            throw new StatementExecutionException("插入的字段未指定!");
        }
        try {
            for (Field field : declaredFields) {
                // 只有标注为测点的属性才需要编制
                if (field.getAnnotation(Measurement.class) == null) {
                    continue;
                }
                measurements.add(field.getName());
                Class<?> type = field.getType();
                switch (type.getTypeName()) {
                    case "java.lang.String":
                        types.add(TSDataType.TEXT);
                        break;
                    case "java.lang.Long":
                        types.add(TSDataType.INT64);
                        break;
                    case "java.lang.Integer":
                        types.add(TSDataType.INT32);
                        break;
                    case "java.lang.Double":
                    case "java.lang.Float":
                        types.add(TSDataType.FLOAT);
                        break;
                    default:types.add(TSDataType.TEXT);
                }
                String methodNamePro = field.getName()
                        .substring(0, 1).toUpperCase() + field.getName().substring(1);
                Method method = target.getDeclaredMethod("get" + methodNamePro);
                method.setAccessible(true);
                Object obj = method.invoke(t);
                // 时间特殊处理
                if (obj instanceof java.util.Date){
                    if(obj != null){
                        obj = DateUtils.parseDateToStr("yyyy-MM-dd HH:mmm:ss",(Date) obj) + "";
                    }else {
                        obj = "";
                    }
                }
                values.add(obj);
            }
            sessionPool.insertAlignedRecord(deviceId, times, measurements, types, values);
        } catch (Exception e) {
            logger.error("数据转换异常", e);
            return;
        }
    }

    /**
     * 执行查询SQL,返回对应Recordable实体的数据结果集
     * @param sql 待执行的SQL
     * @return
     */
    public static <T> List<T> select(String sql, Class<T> target, boolean isCount) {
        logger.info("iot执行sql为:[{}]",sql);
        SpringUtils.getBean(IotDBSession.class).getSessionPool();
        SessionDataSetWrapper wrapper = null;
        List<T> result = new ArrayList<>();
        try {
            wrapper = sessionPool.executeQueryStatement(sql);
            List<String> columnNames = wrapper.getColumnNames(); //返回结果集列名称
            int offset = 0;//如果首列是time列,则结果集数据与列名称数组相差1位下标
            if(columnNames.contains("Time")) {
                offset++;
            }
            while (wrapper.hasNext()) {
                RowRecord rowRecord = wrapper.next();
                T res = target.newInstance();
                List<org.apache.iotdb.tsfile.read.common.Field> fields = rowRecord.getFields(); //不包含时间time列的结果列表,跟结果集列名称数组相差1位下标
                for (int i = 0; i < fields.size(); i++) {
                    // 对齐跳过
                    if(columnNames.contains("Device") && i == 0){
                        i++;// 对齐模式 第一列值是路径 字段多Time 和 Device
                    }
                    java.lang.reflect.Field field = target.getDeclaredField(columnNames.get(i + offset));
                    field.setAccessible(true);
                    field.set(res, getVal(field.getType(), fields.get(i)));
                    field.setAccessible(false);
                }
                // 设置时间序列
                if(isCount){
                    long timestamp = rowRecord.getTimestamp();
                    java.lang.reflect.Field field = target.getDeclaredField("time");
                    field.setAccessible(true);
                    field.set(res, new Date(timestamp));
                    field.setAccessible(false);
                }
                result.add(res);
            }
        } catch (Exception e) {
            logger.error("iot执行异常 [{}]",sql, e);
        } finally {
            if (wrapper != null) {
                wrapper.close();
            }
        }
        return result;
    }

    /**
     * 删除时间戳小于或等于指定时间的数据
     * @param deviceId 删除存储组
     * @return 时间戳小于或等于时间的数据将被删除
     */
    public static void delete(String deviceId) throws Exception {
        SpringUtils.getBean(IotDBSession.class).getSessionPool();
        try {
            sessionPool.deleteTimeseries(deviceId);
        } catch (Exception e) {
            logger.error("Iotdb删除异常" + deviceId, e);
            throw new Exception("Iotdb删除异常");
        }
    }

    /**
     * 删除时间戳小于或等于指定时间的数据
     * @param root 需要删除的类型
     * @param time 待删除的时间点
     * @return 时间戳小于或等于时间的数据将被删除
     */
    public static void deleteRecord(String root, Date time) throws Exception {
        SpringUtils.getBean(IotDBSession.class).getSessionPool();
        Assert.notNull(root, "root 不能为空");
        Assert.notNull(time, "time开始时间不能为空");

        String deviceId = "root.xinao." + root;
        try {
            sessionPool.deleteData(deviceId, time.getTime());
        } catch (Exception e) {
            logger.error("Iotdb删除数据异常" + deviceId, e);
            throw new Exception("Iotdb删除数据异常");
        }
    }

    /**
     * 执行计数SQL
     * @param sql 待执行的计数SQL
     * @return 各列对应的count数
     */
    public static HashMap<String, Integer> count(String sql){
        logger.info("iot执行sql为:[{}]",sql);
        SpringUtils.getBean(IotDBSession.class).getSessionPool();
        SessionDataSetWrapper wrapper = null;
        HashMap<String, Integer> countMap = new HashMap<>();
        try {
            wrapper = sessionPool.executeQueryStatement(sql);
            List<String> columnNames = wrapper.getColumnNames(); //返回结果集列名称
            while (wrapper.hasNext()) {
                RowRecord rowRecord = wrapper.next();
                List<org.apache.iotdb.tsfile.read.common.Field> fields = rowRecord.getFields();
                for (int i = 0; i < fields.size(); i++) {
                    Long count = fields.get(i).getLongV();
                    countMap.put(columnNames.get(i), count.intValue());
                }
            }
        } catch (Exception e) {
            logger.error("IOTDB聚合查询executeCountSQL异常", e);
        } finally {
            if (wrapper != null) {
                wrapper.close();
            }
        }
        return countMap;
    }

    /**
     * 获取字段的结果
     * @param c 期望转换的数据类型
     * @param field 数据库查询的某个字段值
     * @return
     */
    public static Object getVal(Class<?> c, org.apache.iotdb.tsfile.read.common.Field field) {
        Object obj = null;
        //首先判断返回列是否为空值
        if(field.getDataType() == null) {
            return obj;
        }
        if(c == String.class) {
            obj = field.getStringValue();
        } else if(c == Integer.class) {
            obj = field.getIntV();
        } else if(c == Long.class) {
            obj = field.getLongV();
        } else if(c == Float.class) {
            BigDecimal bg = BigDecimal.valueOf(Double.parseDouble(field.getStringValue()));
            bg.setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
            obj = bg.floatValue();
        } else if(c == Double.class) {
            BigDecimal bg = BigDecimal.valueOf(Double.parseDouble(field.getStringValue()));
            bg.setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
            obj = bg.doubleValue();
        } else if(c == Boolean.class) {
            obj = field.getBoolV();
        } else if(c == Date.class) {
            return new Date(field.getLongV());
        }
        return obj;
    }

}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值