背景:

        物联网的业务需求迫使我们需要用到各种各样的组件以及工具,在使用iotdb时序数据库的过程中遇到很多问题,首先批量的插入通过原生session来实现(这个本人已经跑通了),无话可说,官方也是推荐的,但是对于用惯了mybatis的小新,怎么用都感觉别扭,而且网上的例子也很少,我参考了这位大佬的文章全网首发一IoTDB数据库整合MyBatis实现SpringBoot项目CRUD_iotdb 与 mybatis plus_阳光非宅猿的博客-CSDN博客,但是没有跑通,官方不推荐使用jdbc(无法提供高性能吞吐),但一些小量级的增删查,我还是喜欢用mybatis,为此我摸索了一下。

        针对我在测试的时候遇到的问题,现把经验分享出来。

遇到的问题:

        1.启动项目提示:testWhileIdle is true, validationQuery not set

2023-04-26 14:05:39.282 ERROR 13864 --- [           main] com.alibaba.druid.pool.DruidDataSource   : testWhileIdle is true, validationQuery not set

        原因:没有在配置文件中设置(最先的作者可能没遇到这个,不过报错也能用,可以不管)

druid:
  validation-query: 连接测试语句

        2.查询一直报错

                2.1错误一:mismatched input ‘<EOF>,’ excepting ‘{FROM,INTO}‘

                反复检查:是因为validation-query:的连接测试语句不能写成网络上大家正对mysql设置的select 1;

                2.2错误二:java.lang.NullPointerException

     原因:返回结果集的时候类型不能是jdbcType,改成JavaType问题解决,但是...

     2.3错误三:Error attempting to get column “Time” from result set

     原因:不管你需不需要Time字段(需要也不能在select后面写),查询结果都会返回Time字段的值,这是iotdb特有的主键,但是本人试了LONG,VARCHAR,DATE等能想到的类型,都无济于事,但是可以通过Java.lang.String接收到返回的Long类型时间值,通过resultMapper就是无法实现。

     最终解决:通过Map<String,Object>类型将所有数据接收出来,然后再处理(目前我只能这样操作,希望有更好办法的兄弟交流学习)

  3.删除操作,提示成功,但是去库里查询,还在!!!

     我这就无语了,没删除就没删除呗,有错你就提呗,你来个成功,然后结果未实现。

     原因:删除的时候,比如要删除某个时间段的一组数据,必须在设备id后面添加.*,如:

delete from root.XXX.XXX.demo20130424_4.* where time > XXXXXX

最后总算成功通过mybatis实现了自己想要的功能,不过还是有很多不足,还希望有兴趣的同学一起研究。

接下来上代码:

实现过程:

--------------------------------------------------------------------------------------

1.主要依赖:

<dependency>
    <groupId>org.apache.iotdb</groupId>
    <artifactId>iotdb-jdbc</artifactId>
    <version>0.13.0</version>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.21</version>
</dependency>

2.数据库配置

spring:
  datasource:
    username: ****
    password: *******
    driver-class-name: org.apache.iotdb.jdbc.IoTDBDriver
    url: jdbc:iotdb://localhost:6667/
    druid:
      validation-query: select * from *****
    initial-size: 5
    min-idle: 10
    max-active: 50
    max-wait: 60000
    remove-abandoned: true
    remove-abandoned-timeout: 30
    time-between-eviction-runs-millis: 60000
    min-evictable-idle-time-millis: 300000
    test-while-idle: false
    test-on-borrow: false
    test-on-return: false

mybatis:
  mapper-locations: classpath:/mapper/*.xml

#输出sql日志
logging:
  level:
    com.****.iotdb.mapper.IotdbMapper: debug

3.controller,测试用没有入参,实际情况可以自己加

import com.***.iotdb.dao.DeviceDao;
import com.***.iotdb.dao.SaveIotParam;
import com.***.iotdb.dao.SearchIotParam;
import com.***.iotdb.service.IotdbService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author xp
 * @ClassName iotdbDemoController
 * @Description TODO
 * @date 2023/04/24 9:06
 */
@Slf4j
@RestController
@RequestMapping("/iotdbjdbcdemo")
@RequiredArgsConstructor
public class IotdbDemoController {

    @Autowired
    private IotdbService service;
 /** * 新增 * @param data * @return * @throws Exception */
    @PostMapping("/insert")
    public String insert() throws Exception {
        service.insert(data);
        return "SUCCESS";
    }

 /** * 删除 * @param data * @throws Exception */
    @PostMapping("/delete")
    public void delete() throws Exception {
        service.deleteByParam();
    }

 /** * 查询 * @param data * @return * @throws Exception */
    @GetMapping("/queryOrder")
    public List<DeviceDao> queryOrder() throws Exception {
        try {
            List<DeviceDao> v = service.queryOrder();
            return v;
        } catch (Exception e) {
            log.info("查询失败!" + e);
            return null;
        }
    }
}

4.service

4.1接口  

/**
 * @author xp
 * @ClassName IotdbService
 * @Description TODO
 * @date 2023/04/24 9:26
 */
import com.***.iotdb.dao.DeviceDao;
import com.***.iotdb.dao.SaveIotParam;
import com.***.iotdb.dao.SearchIotParam;

import java.util.*;
public interface IotdbService {

    public void insert();

    public void deleteByParam();

    List<DeviceDao> queryOrder();
}

4.2实现类

/**
 * @author xp
 * @ClassName IotdbService
 * @Description TODO
 * @date 2023/04/24 9:26
 */

import com.***.iotdb.dao.DeviceDao;
import com.***.iotdb.dao.SaveIotParam;
import com.***.iotdb.dao.SearchIotParam;
import com.***.iotdb.mapper.IotdbMapper;
import com.***.iotdb.service.IotdbService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class IotdbServiceImpl implements IotdbService {

    @Autowired
    private IotdbMapper mapper;

    @Override
    public void insert() {
        mapper.insert();
    }

    @Override
    public void deleteByParam() {
        mapper.deleteByParam();
    }

    @Override
    public List<DeviceDao> queryOrder(){
        final List<Map<String, Object>> mapList = mapper.queryOrder();
        final List<DeviceDao> result = mapList.stream().map(s -> {
            final DeviceDao deviceDao = new DeviceDao();
            deviceDao.setTime((Date) s.get("Time"));
            deviceDao.setMeasurementTemperature(s.get("temperature").toString());
            deviceDao.setMeasurementWeight(s.get("weight").toString());
            deviceDao.setMeasurementFlow(s.get("flow").toString());
            deviceDao.setMeasurementNumber(s.get("Number").toString());
            return deviceDao;
        }).collect(Collectors.toList());
        return result;
    }
}

5.mapper

import com.***.iotdb.dao.DeviceDao;
import com.***.iotdb.dao.SaveIotParam;
import com.***.iotdb.dao.SearchIotParam;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

/**
 * @author xp
 * @InterfaceName IotdbMapper
 * @Description TODO
 * @date 2023/04/24 14:29
 */
public interface IotdbMapper {
    void insert();

    void deleteByParam();

    List<Map<String, Object>> queryOrder();

}

6.mapper.xml

<?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="com.***.***.mapper.IotdbMapper">

    <resultMap id="BaseResult" type="com.***.***.dao.DeviceDao">
        <collection property="measurementNumber" column="Number" javaType="INTEGER"/>
        <collection property="measurementWeight" column="weight" javaType="DOUBLE"/>
        <collection property="measurementTemperature" column="temperature" javaType="DOUBLE"/>
        <collection property="measurementFlow" column="flow" javaType="DOUBLE"/>
        <collection property="time" column="Time" javaType="DATE"/>
    </resultMap>
<!--    resultMap没有走通,请大神指导-->
    <insert id="insert">
            insert into root.***.***.demo20130424_1 (timestamp, Number, weight, temperature,flow)
            values(2023-04-25T18:28:20.689+08:00,9,7.77,37.99,2.66);
    </insert>
    <delete id="deleteByParam">
        delete from root.***.***.demo20130424_1.* where time &gt; 1682317200000
    </delete>
   
    <select id="queryOrder" resultType="java.util.Map">
        select Number as Number,temperature as temperature,weight as weight,flow as flow from root.zssy.zkj.demo20130424_1 limit 1 offset 0
    </select>
</mapper>

7.记得启动类哦

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

/**
 * @author xp
 * @ClassName IotdbApplication
 * @Description TODO
 * @date 2023/04/24 8:53
 */
@SpringBootApplication
@MapperScan("com.***.iotdb.mapper")
public class IotdbApplication {
    public static void main(String[] args) {
        SpringApplication.run(IotdbApplication.class, args);
        System.out.println("iotdb Demo程序启动成功!");
    }
}

8.测试可行

注意:利用postman测试时,传入的string类型的属性值和整合mysql的用法有区别:

        平时传入的json如下:

{

    "timestamp":"2023-05-04T18:28:20.689+08:00",

    "name":"小明",

    "age":20,

    "sex":"男",

    "address":"西安108号"

}

        但是这里json传参需要给String类型加上单引号' ',否则,运行会报sql错误

{

    "timestamp":"2023-05-04T18:28:20.689+08:00",

    "name":"'小明'",

    "age":20,

    "sex":"'男'",

    "address":"'西安108号'"

}

写在最后:       

        出自物联网新人之手,有什么不对的还请赐教,欢迎感兴趣的小伙伴提出自己宝贵的意见。

参考文献:

 1.https://blog.csdn.net/weixin_42103983/article/details/121580689

 2.快速上手 | IoTDB Website (apache.org)

Logo

一站式 AI 云服务平台

更多推荐