springboot整合TDengine全过程

2025-06-25 05:50

本文主要是介绍springboot整合TDengine全过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《springboot整合TDengine全过程》:本文主要介绍springboot整合TDengine全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教...

环境准备

  • 服务端(Ubuntu 20.04):TDengine-server:2.4.0.5
  • 客户端(Windows 10):TDengine-client:2.4.0.5
  • 依赖:taos-jdbcdriver:2.0.34
  • springboot:spring-boot.version>2.3.7.RELEASE

JDBC-JNI方式

准备

  1. linux或Windows操作系统
  2. Java 1.8以上运行时环境
  3. TDengine-client(使用JDBC-JNI时必须,使用JDBC-RESTful时非必须)

注意:在 Windows 环境开发时需要安装 TDengine 对应的 windows 客户端

依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.taosdata.jdbc</groandroidupId>
            <artifactId>taos-jdbcdriver</artifactId>
            <version>2.0.34</version>
        </dependency>

        <!-- mysql的JDBC数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.34</version>
        </dependency>

        <dependency>
            <groupId>org.myBATis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.17</version>
        </dependency>

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.1.0</version>
        </dependency>

        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.8.1</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

注意:这里taos-jdbcdriver的版本可以参考下面的参数

taos-jdbcdriver 版本TDengine 2.0.x.x 版本TDengine 2.2.x.x 版本TDengine 2.4.x.x 版本JDK 版本
2.0.38XX2.4.0.14 及以上1.8.x
2.0.37XX2.4.0.6 及以上1.8.x
2.0.36X2.2.2.11 及以上2.4.0.0 - 2.4.0.51.8.x
2.0.35X2.2.2.11 及以上2.3.0.0 - 2.4.0.51.8.x
2.0.33 - 2.0.342.0.3.0 及以上2.2.0.0 及以上2.4.0.0 - 2.4.0.51.8.x
2.0.31 - 2.0.322.1.3.0 - 2.1.7.7XX1.8.x
2.0.22 - 2.0.302.0.18.0 - 2.1.2.1XX1.8.x
2.0.12 - 2.0.212.0.8.0 - 2.0.17.4XX1.8.x
2.0.4 - 2.0.112.0.0.0 - 2.0.7.3XX1.8.x

实体类

@Data
public class Temperature {

    private Timestamp ts;
    private float temperature;
    private String location;
    private int tbIndex;
}

TDengine 类型对应Java类型

TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下

TDengine DataTypeJDBCType (driver 版本 < 2.0.24)JDBCType (driver 版本 >= 2.0.24)
TIMESTAMPjava.lang.Longjava.sql.Timestamp
INTjava.lang.Integerjava.lang.Integer
BIGINTjava.lang.Longjava.lang.Long
FLOATjava.lang.Floatjava.lang.Float
DOUBLEjava.lang.Doublejava.lang.Double
SMALLINTjava.lang.Shortjava.lang.Short
TINYINTjava.lang.Bytejava.lang.Byte
BOOLjava.lang.Booleanjava.lang.Boolean
BINARYjava.lang.Stringbyte array
NCHARjava.lang.Stringjava.lang.String
jsON-java.lang.String

注意:JSON类型仅在tag中支持

Mapper

@Repository
@Mapper
public interface TemperatureMapper{

    @Update("CREATE TABLE if not exists temperature(ts timestamp, temperature float) tags(location nchar(64), tbIndex int)")
    int createSuperTable();

    @Update("create table #{tbName} using temperature tags( #{location}, #{tbindex})")
    int createTable(@Param("tbName") String tbName, @Param("location") String location, @Param("tbindex") int tbindex);

    @Update("drop table if exists temperature")
    void dropSuperTable();

    @Insert("insert into t${tbIndex}(ts, temperature) values(#{ts}, #{temperature})")
    int insertOne(Temperature one);

    @Select("select * from temperature where location = #{location}")
    List<Temperature> selectTemperatureByLocation(@Param("location") String location);

    @Select("select * from temperature")
    List<Temperature> selectAll();

    @Select("select count(*) from temperature where temperature = 0.5")
    int selectCount();

    @Update("create database if not exists test")
    void createDB();

    @Update("drop database if exists test")
    void dropDB();
}

配置类

@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = {"com.yolo.springboottdengine.mapper"}, sqlSessionFactoryRef = "TDengineSqlSessionFactory")
public class TDengineConfiguration {

    @Bean(name = "TDengineDataSource")
    public DataSource tdengineDataSource() throws Exception {

        // 125  TDengine测试环境
        String taosHost = "127.0.0.1";
        String taosPort = "6030";
        String taosUsername = "root";
        String taosPassword = "root";
        String taosDB = "test";


        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.taosdata.jdbc.TSDBDriver");
        dataSource.setUrl("jdbc:TAOS://" + taosHost + ":" + taosPort + "/" + taosDB
               + "?charset=UTF-8&locale=zh_CN.UTF-8&timezone=UTC-8");

        dataSource.setPassword(taosPassword);
        dataSource.setUsername(taosUsername);
        dataSource.setInitialSize(5);
        dataSource.setMinIdle(10);
        dataSource.setMaxActive(100);
        dataSource.setMaxWait(30000);
        dataSource.setValidationQuery("select server_status()");
        return dataSource;
    }


    @Bean(name = "TDengineTransactionManager")
    public DataSourceTransactionManager tdengineTransactionManager() throws Exception {
        return new DataSourceTransactionManager(tdengineDataSource());
    }

    @Bean(name = "TDengineSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("TDengineDataSource") DataSource dataSource, PageHelper pageHelper) throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setPlugins(pageHelper);
        return sessionFactory.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("TDengineSqlSessionFactory")SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean
    public PageHelper pageHelper() {
        PageHelper pageHelper = new PageHelper();
        Properties p = new Properties();
        p.setProperty("offsetASPageNum", "true");
        p.setProperty("rowBoundsWithCount", "true");
        p.setProperty("reasonable", "true");
        p.setProperty("dialect", "mysql");
        pageHelper.setProperties(p);
        return pageHelper;
    }

}

测试类

@SpringBootTest
@RunWith(SpringRunner.class)
public class TemperatureTest {

    private static final Random random = new Random(System.currentTimeMillis());
    private static final String[] locations = {"北京", "上海", "深圳", "广州", "杭州"};

    @Autowired
    private TemperatureMapper temperatureMapper;

    @Test
    public void createDatabase(){
        temperatureMapper.dropDB();
        temperatureMapper.createDB();
    }

    @Test
    public void init() {
        temperatureMapper.dropSuperTable();
        // create table temperature
        temperatureMapper.createSuperTable();
        // create table t_X using temperature
        for (int i = 0; i < 10; i++) {
            temperatureMapper.createTable("t" + i, locations[random.nextInt(locations.length)], i);
        }
        // insert into table
        int affectRows = 0;
        // insert 10 tables
        for (int i = 0; i < 10; i++) {
            // each table insert 5 rows
            for (int j = 0; j < 5; j++) {
                Temperature one = new Temperature();
                one.setTs(new Timestamp(System.currentTimeMillis()));
                one.setTemperature(random.nextFloat() * 50);
                one.setLocation("望京");
                one.setTbIndex(i);
                affectRows += temperatureMapper.insertOne(one);
            }
        }
        Assert.assertEquals(50, affectRows);
    }

    /**
     * 根据名称查询
     */
    @Test
    public void testSelectByLocation() {
        List<Temperature> temperatureList = temperatureMapper.selectTemperatureByLocation("广州");
        System.out.println(temperatureList);
    }

    /**
     * 查询所有
     */
    @Test
    public void testSelectAll() {
        List<Temperature> temperatures = temperatureMapper.selectAll();
        System.out.println(temperatures.size());
    }

    /**
     * 插入数据
     */
    @Test
    public void testInsert() {
        //时间一样的时候,数据不会发现改变   1604995200000
        Temperature one = new Temperature();
        one.setTs(new Timestamp(1604995222224L));
        one.setTemperature(1.2f);
        int i = temperatureMapper.insertOne(one);
        System.out.println(i);
    }

    /**
     * 查询数量
     */
    @Test
    public void testSelectCount() {
        int count = temperatureMapper.selectCount();
        System.out.println(count);
    }

    /**
     * 分页查询
   China编程  */
    @Test
    public void testPage() {
        //查询之前,设置当前页和当前页的数量
        PageHelper.startPage(1, 2);
        List<Temperature> temperatureList = temperatureMapper.selectAll();
        //把查询结果放入到pageInfo对象中
        PageInfo<Temperature> pageInfo = new PageInfo<>(temperatureList);
        long total = pageInfo.getTotal();
        int pageNum = pageInfo.getPageNum();
        List<Temperature> list = pageInfo.getList();
        System.out.println("总数:" + total);
        System.out.println("页数:" + pageNum);
        System.out.println(list);

    }
}

RESTful方式

实体类

public class Weather {
//    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS", timezone = "GMT+8")
    private Timestamp ts;
    private Float temperature;
    private Float humidity;
    private String location;
    private String note;
    private int groupId;
    
    //省略构造方法和get/set方法
}
public class TDengineRestfulInfo {

    private long  rows;
    private String status;
    private List<String> head;
    private List<List<String>> data;
    private List<List<String>> column_meta;
    //省略构造方法和get/set方法
}

配置类

app.td.rest.url=http://127.0.0.1:6041/rest/sql
app.td.rest.basic=Basic cm9vd90
app.td.db=test

测试类

@SpringBootTest
@RunWith(SpringRunner.class)
public class WeatherTest {

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

    @Value("${app.td.rest.url}")
    @NotBlank
    private String tdRestUrl;

    @Value("${app.td.rest.basic}")
    @NotBlank
    private String tdRestBasic;

    @Value("${app.td.db}")
    @NotBlank
    private String db;

    private final Random random = new Random(System.currentTimeMillis());
    private final String[] locations = {"北京", "上海", "广州", "深圳", "天津"};

    @Test
    public void createDB() {
        String sql = "create database if not exists test";
        String url = tdRestUrl;
        tdengineRestful(url, sql);
    }

    @Test
    public void dropDB() {
        String sql = "drop database if exists test";
        tdengineRestful2(tdRestUrl, sql);
    }

    @Test
    public void createSuperTable() {
        String sql = "create table if not exists test.wandroideather (ts timestamp,temperature float,humidity float,note binary(64)) tags(location nchar(64), groupId int)";
        tdengineRestful2(tdRestUrl, sql);
    }

    @Test
    public void createTable() {
        String url = tdRestUrl + "/" + db;
        long ts = System.currentTimeMillis();
        long thirtySec = 1000 * 30;
        Weather weather = new Weather(new Timestamp(ts + (thirtySec)), 30 * random.nextFloat(), random.nextInt(100));
        weather.setLocation(locations[random.nextInt(locations.length)]);
        weather.setGroupId(1);
        weather.setNote(python"note-" + 1);
  python      //create table if not exists test.t#{groupId} using test.weather tags(#{location},#{groupId})
        StringBuilder sb = new StringBuilder();
        sb.append("create table if not exists test.t")
                .append(weather.getGroupId()).append(" ")
                .append("using test.weather tags(")
                .append("'").append(weather.getLocation()).append("'").append(",")
                .append(weather.getGroupId()).append(")");
        String s = sb.toString();

        tdengineRestful2(url, sb.toString());
    }

    @Test
    public void insertTable() {
        String url = tdRestUrl + "/" + db;
        long ts = System.currentTimeMillis();
        long thirtySec = 1000 * 30;

        for (int i = 0; i < 5; i++) {
            Weather weather = new Weather(new Timestamp(ts + (thirtySec * i)), 30 * random.nextFloat(), random.nextInt(100));
            weather.setLocation(locations[random.nextInt(locations.length)]);
            weather.setGroupId(1);
            weather.setNote("note-" + 1);
            //insert into test.t#{groupId} (ts, temperature, humidity, note)values (#{ts}, ${temperature}, ${humidity}, #{note})
            StringBuilder sb = new StringBuilder();
            sb.append("insert into test.t").append(weather.getGroupId()).append(" ")
                    .append("(ts, temperature, humidity, note)").append(" ")
                    .append("values (").append(weather.getTs().getTime()).append(",")
                    .append(weather.getTemperature()).append(",")
                    .append(weather.getHumidity()).append(",")
                    .append("'").append(weather.getNote()).append("'")
                    .append(")");
            String sql = sb.toString();
            tdengineRestful2(url,sql);
        }

    }

    @Test
    public void selectCount(){
        String url = tdRestUrl + "/" + db;
        String sql = "select count(*) from test.weather";
        TDengineRestfulInfo tDengineRestfulInfo = tdengineRestful2(url, sql);
        System.out.println(tDengineRestfulInfo);
    }

    @Test
    public void selectOne(){
        String url = tdRestUrl + "/" + db;
        String sql = "select * from test.weather where humidity = 13";
        TDengineRestfulInfo tDengineRestfulInfo = tdengineRestful2(url, sql);
        System.out.println(tDengineRestfulInfo);

    }

    @Test
    public void selectTbname(){
        String url = tdRestUrl + "/" + db;
        String sql = "select tbname from test.weather";
        TDengineRestfulInfo tDengineRestfulInfo = tdengineRestful2(url, sql);
        System.out.println(tDengineRestfulInfo);

    }

    @Test
    public void selectLastOne(){
        String url = tdRestUrl + "/" + db;
        String sql = "select last_row(*), location, groupid from test.weather";
        TDengineRestfulInfo tDengineRestfulInfo = tdengineRestful2(url, sql);
        System.out.println(tDengineRestfulInfo);
    }

    @Test
    public void selectAVG(){
        String url = tdRestUrl + "/" + db;
        String sql = "select avg(temperature), avg(humidity) from test.weather interval(1m)";
        TDengineRestfulInfo tDengineRestfulInfo = tdengineRestful2(url, sql);
        System.out.println(tDengineRestfulInfo);

    }

    @Test
    public void selectLimit(){
        String url = tdRestUrl + "/" + db;
        String sql = "select * from test.weather order by ts desc limit 3";
        TDengineRestfulInfo tDengineRestfulInfo = tdengineRestful2(url, sql);
        System.out.println(tDengineRestfulInfo);
    }



    public TDengineRestfulInfo tdengineRestful2(String url, String sql) {

        TDengineRestfulInfo tDengineRestfulInfo = null;

        // 获取默认配置 的OkHttpClient 对象
        OkHttpClient httpClient = new OkHttpClient.Builder().build();

        MediaType mediaType = okhttp3.MediaType.parse("application/json; charset=utf-8");
        RequestBody requestBody = RequestBody.create(mediaType, sql);

        Request request = new Request.Builder()
                .url(url)
                .addHeader("Authorization", tdRestBasic)
                .post(requestBody)
                .build();

        Response response = null;
        try {
            response = httpClient.newCall(request).execute();
            if (response.code() == HttpStatus.OK.value()) {
                if (response.body() != null) {
                    String s = response.body().string();
                    tDengineRestfulInfo = JSONUtil.toBean(s, TDengineRestfulInfo.class);
                }
            } else {
                logger.error("tdengineRestful 查询状态码异常,状态码是:" + response.code() + " ,异常消息是:" + response.message());
            }
        } catch (Exception e) {
            logger.error("tdengineRestful 查询出现错误:" + e);
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return tDengineRestfulInfo;

    }
}

注意这里新增一条数据的时候ts,俩种方式,要注意引号

“ts”: 1626324781093
“ts”: “2021-07-19 14:53:01.093”

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程China编程(www.chinasem.cn)。

这篇关于springboot整合TDengine全过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1155202

相关文章

SpringBoot集成P6Spy的实现示例

《SpringBoot集成P6Spy的实现示例》本文主要介绍了SpringBoot集成P6Spy的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录本节目标P6Spy简介抛出问题集成P6Spy1. SpringBoot三板斧之加入依赖2. 修改

Spring Integration Redis 使用示例详解

《SpringIntegrationRedis使用示例详解》本文给大家介绍SpringIntegrationRedis的配置与使用,涵盖依赖添加、Redis连接设置、分布式锁实现、消息通道配置及... 目录一、依赖配置1.1 Maven 依赖1.2 Gradle 依赖二、Redis 连接配置2.1 配置 R

Spring Security重写AuthenticationManager实现账号密码登录或者手机号码登录

《SpringSecurity重写AuthenticationManager实现账号密码登录或者手机号码登录》本文主要介绍了SpringSecurity重写AuthenticationManage... 目录一、创建自定义认证提供者CustomAuthenticationProvider二、创建认证业务Us

Java Stream流以及常用方法操作实例

《JavaStream流以及常用方法操作实例》Stream是对Java中集合的一种增强方式,使用它可以将集合的处理过程变得更加简洁、高效和易读,:本文主要介绍JavaStream流以及常用方法... 目录一、Stream流是什么?二、stream的操作2.1、stream流创建2.2、stream的使用2.

Java对接MQTT协议的完整实现示例代码

《Java对接MQTT协议的完整实现示例代码》MQTT是一个基于客户端-服务器的消息发布/订阅传输协议,MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛,:本文主要介绍Ja... 目录前言前置依赖1. MQTT配置类代码解析1.1 MQTT客户端工厂1.2 MQTT消息订阅适配器1.

Spring Boot项目如何使用外部application.yml配置文件启动JAR包

《SpringBoot项目如何使用外部application.yml配置文件启动JAR包》文章介绍了SpringBoot项目通过指定外部application.yml配置文件启动JAR包的方法,包括... 目录Spring Boot项目中使用外部application.yml配置文件启动JAR包一、基本原理

SpringBoot加载profile全面解析

《SpringBoot加载profile全面解析》SpringBoot的Profile机制通过多配置文件和注解实现环境隔离,支持开发、测试、生产等不同环境的灵活配置切换,无需修改代码,关键点包括配置文... 目录题目详细答案什么是 Profile配置 Profile使用application-{profil

Java中InputStream重复使用问题的几种解决方案

《Java中InputStream重复使用问题的几种解决方案》在Java开发中,InputStream是用于读取字节流的类,在许多场景下,我们可能需要重复读取InputStream中的数据,这篇文章主... 目录前言1. 使用mark()和reset()方法(适用于支持标记的流)2. 将流内容缓存到字节数组

Java慢查询排查与性能调优完整实战指南

《Java慢查询排查与性能调优完整实战指南》Java调优是一个广泛的话题,它涵盖了代码优化、内存管理、并发处理等多个方面,:本文主要介绍Java慢查询排查与性能调优的相关资料,文中通过代码介绍的非... 目录1. 事故全景:从告警到定位1.1 事故时间线1.2 关键指标异常1.3 排查工具链2. 深度剖析:

Springboot项目登录校验功能实现

《Springboot项目登录校验功能实现》本文介绍了Web登录校验的重要性,对比了Cookie、Session和JWT三种会话技术,分析其优缺点,并讲解了过滤器与拦截器的统一拦截方案,推荐使用JWT... 目录引言一、登录校验的基本概念二、HTTP协议的无状态性三、会话跟android踪技术1. Cook