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; } }
iotdb操作工具类
于 2024-04-09 16:25:48 首次发布