JFinal中使用IoTDB时序数据库

文章目录

前言

使用步骤

1.引入库

2.JFinal自定义一个IoTDB的插件

3.插件启动配套的工具类:IoTDBUtils

4.JFinal插件启动

5.IoTDB的数据插入

6.IoTDB的数据查询

总结



前言

随着科技的快速发展,物联网已经变成了生活中处处存在的技术,物联网的存在必然会产生数据,而且物联网中的各种传感器数据量是大量的,时序性的,这就需要时序数据库,本实例使用的的是JFinal极速 web 开发框架,时序数据库IoTDB 是清华大学主导的 Apache 孵化项目,是一款专为物联网时序数据打造的数据库,提供数据采集、存储、分析的功能。

使用步骤

1.引入库

<!-- IoTDB时序数据库 -->
        <dependency>
            <groupId>org.apache.iotdb</groupId>
            <artifactId>iotdb-session</artifactId>
            <version>0.13.2</version>
            <exclusions>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

2.JFinal自定义一个IoTDB的插件

public class IoTDBPlugin implements IPlugin {

    private static final Logger log = Logger.getLogger(IoTDBPlugin.class);

    protected String host;
    protected int port;
    protected List<String> nodeUrls;
    protected int fetchSize=-1;
    protected String username;
    protected String password;
    protected int thriftDefaultBufferSize;
    protected int thriftMaxFrameSize;
    protected boolean enableCacheLeader;
    protected Version version;

    protected Session session;

    public IoTDBPlugin() {

    }

    public IoTDBPlugin(String host,int port) {
        this.host=host;
        this.port=port;
    }

    public IoTDBPlugin(List<String> nodeUrls) {
        this.nodeUrls=nodeUrls;
    }

    public IoTDBPlugin(String host,int port,String username,String password,
                       int fetchSize,int thriftDefaultBufferSize,
                       int thriftMaxFrameSize,boolean enableCacheLeader,Version version) {
        this.host=host;
        this.port=port;
        this.username=username;
        this.password=password;
        this.fetchSize=fetchSize;
        this.thriftDefaultBufferSize=thriftDefaultBufferSize;
        this.thriftMaxFrameSize=thriftMaxFrameSize;
        this.enableCacheLeader=enableCacheLeader;
        this.version=version;
    }

    @Override
    public boolean start() {
        if(this.host!=null)
        {
            // 指定一个可连接节点
            session =
                    new Session.Builder()
                            .host(this.host)
                            .port(this.port)
                            .build();
        }
        else if(this.nodeUrls!=null)
        {
            // 指定多个可连接节点
            session =
                    new Session.Builder()
                            .nodeUrls(this.nodeUrls)
                            .build();
        }
        else if(this.fetchSize!=-1)
        {
            // 其他配置项
            session =
                    new Session.Builder()
                            .fetchSize(this.fetchSize)
                            .username(this.username)
                            .password(this.password)
                            .thriftDefaultBufferSize(this.thriftDefaultBufferSize)
                            .thriftMaxFrameSize(this.thriftMaxFrameSize)
                            .enableCacheLeader(this.enableCacheLeader)
                            .version(this.version)
                            .build();
        }
        else
        {
            // 全部使用默认配置
            session = new Session.Builder().build();
        }

        try {
            session.open();
            log.info("iotdb连接成功~");
            // 设置时区
            session.setTimeZone("+08:00");
        } catch (IoTDBConnectionException e) {
            e.printStackTrace();
        } catch (StatementExecutionException e) {
            e.printStackTrace();
        }
        IoTDBUtils.AddSession(session);
        return true;
    }

    @Override
    public boolean stop() {
        try {
            this.session.close();
            IoTDBUtils.close();
        } catch (IoTDBConnectionException e) {
            e.printStackTrace();
        }
        return false;
    }
}

3.插件启动配套的工具类:IoTDBUtils

public class IoTDBUtils {

    static String key;

    public IoTDBUtils() {
    }

    /**
     *  root.adlot.
     * @param _key
     */
    public static IoTDBUtils use(String _key) {
        key=_key;
        return new IoTDBUtils();
    }

    private static final Logger log = Logger.getLogger(IoTDBUtils.class);

    static Session session;

    /**
     * 初始化Session
     * @param _session
     */
    public static void AddSession(Session _session) {
        if (_session == null) {
            throw new IllegalArgumentException("IoTDB Session can not be null");
        } else {
            session = _session;
        }
    }

    /**
     *  关闭Session
     * @throws IoTDBConnectionException
     */
    public static void close() throws IoTDBConnectionException {
        if (session != null) {
            session.close();
        }
    }

    /**
     *  获取Session
     * @return
     */
    public static Session getSession() {
        return session;
    }

    /**
     * description: 带有数据类型的添加操作 - insertRecord没有指定类型
     *
     * @param * @param deviceId:节点路径如:root.a1eaKSRpRty.CA3013A303A25467
     *          time:时间戳
     *          measurementsList:物理量 即:属性
     *          type:数据类型: BOOLEAN((byte)0), INT32((byte)1),INT64((byte)2),FLOAT((byte)3),DOUBLE((byte)4),TEXT((byte)5),VECTOR((byte)6);
     *          valuesList:属性值 --- 属性必须与属性值一一对应
     * @return
     */
    public static void insertRecordType(String deviceId, Long time, List<String> measurementsList, TSDataType type, List<Object> valuesList) throws StatementExecutionException, IoTDBConnectionException, ServerException {
        if (measurementsList.size() != valuesList.size()) {
            throw new ServerException("measurementsList 与 valuesList 值不对应");
        }
        List<TSDataType> types = new ArrayList<>();
        measurementsList.forEach(item -> {
            types.add(type);
        });
        session.insertRecord(deviceId, time, measurementsList, types, valuesList);
    }

    /**
     * description: 带有数据类型的添加操作 - insertRecord没有指定类型
     *
     * @param deviceId:节点路径如:root.a1eaKSRpRty.CA3013A303A25467
     * @param time:时间戳
     * @param measurementsList:物理量                             即:属性
     * @param valuesList:属性值                                   --- 属性必须与属性值一一对应
     * @return
     */
    public static void insertRecord(String deviceId, Long time, List<String> measurementsList, List<String> valuesList)
            throws StatementExecutionException, IoTDBConnectionException, ServerException {
        if (measurementsList.size() == valuesList.size()) {
            session.insertRecord(deviceId, time, measurementsList, valuesList);
        } else {
            log.error("measurementsList 与 valuesList 值不对应");
        }
    }

    /**
     * description: 批量插入
     */
    public static void insertRecords(List<String> deviceIdList, List<Long> timeList, List<List<String>> measurementsList, List<List<String>> valuesList) throws StatementExecutionException, IoTDBConnectionException, ServerException {
        if (measurementsList.size() == valuesList.size()) {
            session.insertRecords(deviceIdList, timeList, measurementsList, valuesList);
        } else {
            log.error("measurementsList 与 valuesList 值不对应");
        }
    }

    /**
     * description: 插入操作
     *
     * @param deviceId:节点路径如:root.a1eaKSRpRty.CA3013A303A25467
     * @param time:时间戳
     * @param schemaList:                                      属性值 + 数据类型 例子: List<MeasurementSchema> schemaList = new ArrayList<>();  schemaList.add(new MeasurementSchema("breath", TSDataType.INT64));
     * @param maxRowNumber:
     * @return
     */
    public static void insertTablet(String deviceId, Long time, List<MeasurementSchema> schemaList, List<Object> valueList, int maxRowNumber) throws StatementExecutionException, IoTDBConnectionException {

        Tablet tablet = new Tablet(deviceId, schemaList, maxRowNumber);
        // 向iotdb里面添加数据
        int rowIndex = tablet.rowSize++;
        tablet.addTimestamp(rowIndex, time);
        for (int i = 0; i < valueList.size(); i++) {
            tablet.addValue(schemaList.get(i).getMeasurementId(), rowIndex, valueList.get(i));
        }
        if (tablet.rowSize == tablet.getMaxRowNumber()) {
            session.insertTablet(tablet, true);
            tablet.reset();
        }
        if (tablet.rowSize != 0) {
            session.insertTablet(tablet);
            tablet.reset();
        }
    }

    /**
     * description: 根据SQL查询
     */
    public static SessionDataSet query(String sql) throws StatementExecutionException, IoTDBConnectionException {
        return session.executeQueryStatement(sql);
    }

    /**
     * description: 删除分组 如 root.a1eaKSRpRty
     *
     * @param groupName:分组名称
     * @return
     */
    public static void deleteStorageGroup(String groupName) throws StatementExecutionException, IoTDBConnectionException {
        session.deleteStorageGroup(groupName);
    }

    /**
     * description: 根据Timeseries删除  如:root.a1eaKSRpRty.CA3013A303A25467.breath  (个人理解:为具体的物理量)
     */
    public static void deleteTimeseries(String timeseries) throws StatementExecutionException, IoTDBConnectionException {
        session.deleteTimeseries(timeseries);
    }

    /**
     * description: 根据Timeseries批量删除
     */
    public static void deleteTimeserieList(List<String> timeseriesList) throws StatementExecutionException, IoTDBConnectionException {
        session.deleteTimeseries(timeseriesList);
    }

    /**
     * description: 根据分组批量删除
     */
    public static void deleteStorageGroupList(List<String> storageGroupList) throws StatementExecutionException, IoTDBConnectionException {
        session.deleteStorageGroups(storageGroupList);
    }

    /**
     * description: 根据路径和结束时间删除 结束时间之前的所有数据
     */
    public static void deleteDataByPathAndEndTime(String path, Long endTime) throws StatementExecutionException, IoTDBConnectionException {
        session.deleteData(path, endTime);
    }

    /**
     * description: 根据路径集合和结束时间批量删除 结束时间之前的所有数据
     */
    public static void deleteDataByPathListAndEndTime(List<String> pathList, Long endTime) throws StatementExecutionException, IoTDBConnectionException {
        session.deleteData(pathList, endTime);
    }

    /**
     * description: 根据路径集合和时间段批量删除
     */
    public static void deleteDataByPathListAndTime(List<String> pathList, Long startTime, Long endTime)
            throws StatementExecutionException, IoTDBConnectionException {
        session.deleteData(pathList, startTime, endTime);
    }

    /**
     *  执行语句无返回值
     * @param sql
     * @throws IoTDBConnectionException
     * @throws StatementExecutionException
     */
    public static void exesql(String sql) throws IoTDBConnectionException, StatementExecutionException {
        session.executeNonQueryStatement(sql);
    }

    /**
     *   SessionDataSet 转 List<Record>
     * @param deviceid
     * @param sessionDataSet
     * @return
     * @throws IoTDBConnectionException
     * @throws StatementExecutionException
     */
    public static List<Record> ToListRecord(String deviceid,SessionDataSet sessionDataSet) throws IoTDBConnectionException, StatementExecutionException {
        List<Record> list=new ArrayList<Record>();
        List<String> listcols = sessionDataSet.getColumnNames();    //字段信息
        sessionDataSet.setFetchSize(1); // 只一个一个的获取
        int fetchSize = sessionDataSet.getFetchSize();
        int nextNum = 0;
        while(sessionDataSet.hasNext()) {
            RowRecord next = sessionDataSet.next(); // 如果获取的数据量
            List<Field> listRes = next.getFields();     //数据信息
            Record record=new Record();
            record.set("time",next.getTimestamp());
            for (int i = 0; i < listRes.size(); i++) {
                String colname=listcols.get(i+1);
                colname = colname.substring(colname.indexOf(deviceid.replaceAll("-","_"))+deviceid.length()+1);
                Field field = listRes.get(i);
                if(field.getDataType()!=null)
                {
                    if(field.getDataType()==TSDataType.DOUBLE)
                    {
                        record.set(colname,field.getDoubleV());
                    }
                    else if(field.getDataType()==TSDataType.FLOAT)
                    {
                        record.set(colname,field.getFloatV());
                    }
                    else if(field.getDataType()==TSDataType.INT32||field.getDataType()==TSDataType.INT64)
                    {
                        record.set(colname,field.getIntV());
                    }
                    else if(field.getDataType()==TSDataType.BOOLEAN)
                    {
                        record.set(colname,field.getBoolV());
                    }
                    else if(field.getDataType()==TSDataType.TEXT)
                    {
                        record.set(colname,field.getStringValue());
                    }
                    else
                    {
                        record.set(colname,field.getStringValue());
                    }
                }
                else
                {
                    record.set(colname,null);
                }
            }
            list.add(record);
            nextNum++;
        }
        sessionDataSet.closeOperationHandle();
        return list;
    }

    /**
     *  查询出单参数的时间折线图数据集
     * @param deviceid
     * @param sessionDataSet
     * @return
     * @throws IoTDBConnectionException
     * @throws StatementExecutionException
     */
    public static List<Object> ToList(String deviceid,SessionDataSet sessionDataSet) throws IoTDBConnectionException, StatementExecutionException {

        List<Object> data;
        List<Object> list_data = new ArrayList<Object>();

        List<String> listcols = sessionDataSet.getColumnNames();    //字段信息
        sessionDataSet.setFetchSize(1); // 只一个一个的获取
        int fetchSize = sessionDataSet.getFetchSize();
        int nextNum = 0;
        while(sessionDataSet.hasNext()) {
            RowRecord next = sessionDataSet.next(); // 如果获取的数据量
            List<Field> listRes = next.getFields();     //数据信息
            data=new ArrayList<Object>();
            data.add(next.getTimestamp());              //时间
            for (int i = 0; i < listRes.size(); i++) {
                String colname=listcols.get(i+1);
                colname = colname.substring(colname.indexOf(deviceid.replaceAll("-","_"))+deviceid.length()+1);
                Field field = listRes.get(i);
                if(field.getDataType()!=null)
                {
                    if(field.getDataType()==TSDataType.DOUBLE)
                    {
                        data.add(field.getDoubleV());
                    }
                    else if(field.getDataType()==TSDataType.FLOAT)
                    {
                        data.add(field.getFloatV());
                    }
                    else if(field.getDataType()==TSDataType.INT32||field.getDataType()==TSDataType.INT64)
                    {
                        data.add(field.getIntV());
                    }
                }
                else
                {
                    data.add(null);
                }
            }
            list_data.add(data);
            nextNum++;
        }
        sessionDataSet.closeOperationHandle();
        return list_data;
    }
}

4.JFinal插件启动

jfinal的继承“JFinalConfig”的类文件的“configPlugin(Plugins plugins)”添加插件,启动之后即可连接到IoTDB,我使用的是默认连接,IoTDB只使用地址和端口:

IoTDBPlugin ioTDBPlugin=new IoTDBPlugin(p.get("iotdb.host"),p.getInt("iotdb.port"));
plugins.add(ioTDBPlugin);

5.IoTDB的数据插入

List<String> measurementsList = new ArrayList<>();
            List<Double> valuesList = new ArrayList<>();
            String deviceId ="root.demo.group.deviceId";

            measurementsList.add("temperature");
            valuesList.add(30.3);
            
            try {
                IoTDBUtils.insertRecord(deviceId,new Date().getTime(), measurementsList, valuesList);
            } catch (StatementExecutionException e) {
                e.printStackTrace();
            } catch (IoTDBConnectionException e) {
                e.printStackTrace();
            } catch (ServerException e) {
                e.printStackTrace();
            }

6.IoTDB的数据查询

String sql="select temperature from root.demo.group.deviceid where time>=2020-10-10 12:00:00 and time <=2020-10-11 12:00:00";
SessionDataSet sessionDataSet = null;
        try {
            sessionDataSet = IoTDBUtils.query(sql);
            return sessionDataSet;
        } catch (StatementExecutionException e) {
            e.printStackTrace();
        } catch (IoTDBConnectionException e) {
            e.printStackTrace();
        }

解析“SessionDataSet”即可,可以参考IoTDBUtils方法中的ToList,生成类似如下的折线图。(我做的是多轴的)


总结

IoTDB我自测程序不断写入,上百万的参数数据,查询无压力。解决了当前的物联网项目中的大量数据的存储和查询问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值