记录一下使用SpringBoot+Mybatis整合TDengine数据库的Demo,支持分页返回查询数据
分页查询
模拟插入数据 批量插入和单条插入数据
TDengine Database 数据库查询数据
在使用之前,需要先安装好TDengine Datavase
首先进入TDengine数据库,创建数据库和超级表,这里使用的是按照设备的imei来存储温湿度值(物联网方式)
[root@192 ~]# taos
Welcome to the TDengine Command Line Interface, Client Version:3.2.3.0
Copyright (c) 2023 by TDengine, all rights reserved.
******************************** Tab Completion ************************************
* The TDengine CLI supports tab completion for a variety of items, *
* including database names, table names, function names and keywords. *
* The full list of shortcut keys is as follows: *
* [ TAB ] ...... complete the current word *
* ...... if used on a blank line, display all supported commands *
* [ Ctrl + A ] ...... move cursor to the st[A]rt of the line *
* [ Ctrl + E ] ...... move cursor to the [E]nd of the line *
* [ Ctrl + W ] ...... move cursor to the middle of the line *
* [ Ctrl + L ] ...... clear the entire screen *
* [ Ctrl + K ] ...... clear the screen after the cursor *
* [ Ctrl + U ] ...... clear the screen before the cursor *
**************************************************************************************
Server is Community Edition.
taos>
创建数据库 两种格式,其中第二种支持不存在才创建
create database td_device_log;
create database if not exists td_device_log;
taos> create database td_device_log;
Create OK, 0 row(s) affected (0.959227s)
taos> create database if not exists td_device_log;
Create OK, 0 row(s) affected (0.002038s)
创建超级表,时间戳 imei唯一的编码(可看一类数据的或者某个设备的成唯一ID),temp和hum是温湿度的字段
taos> use td_device_log;
Database changed.
taos> CREATE STABLE device_env_imei(time_stamp TIMESTAMP, imei varchar(64), temp varchar(64), hum varchar(64)) TAGS (imei_point varchar(64));
Create OK, 0 row(s) affected (0.014501s)
taos>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>boot.example.mybatis.tdengine</groupId>
<artifactId>boot-example-mybatis-tdengine</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>boot-example-mybatis-tdengine</name>
<description>boot-example-mybatis-tdengine</description>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>3.2.8</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.2</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-spring-boot-starter</artifactId>
<version>1.1.17</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.yml</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.yml</include>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.5.8</version>
</plugin>
</plugins>
</build>
</project>
关键点,需要与TDengine版本匹配,否则可能出现错误
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>3.2.8</version>
</dependency>
application.properties(这里直接使用的6030,需要客户端驱动的原生链接方式)
server.port=8060
spring.application.name=boot-example-mybatis-tdengine
spring.datasource.driver-class-name=com.taosdata.jdbc.TSDBDriver
spring.datasource.url=jdbc:TAOS://192.168.1.6:6030/td_device_log?charset=UTF-8&locale=en_US.UTF-8&timezone=UTC-8
spring.datasource.username=root
spring.datasource.password=taosdata
DeviceEnvImei.java
package boot.example.tdengine.domain;
import lombok.Data;
@Data
public class DeviceEnvImei {
private long timeStamp;
private String imei;
private String temp;
private String hum;
}
DeviceEnvImeiRequestVo.java
package boot.example.tdengine.domain;
import lombok.Data;
@Data
public class DeviceEnvImeiRequestVo {
private long startStamp;
private long endStamp;
private String imei;
private Long limit;
private Long offset;
}
Response.java
package boot.example.tdengine.domain;
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Response {
private boolean state;
private int code;
private String msg;
private Object data;
private long timestamp;
public Response() {}
public Response(boolean state, int code, String msg) {
this.state = state;
this.code = code;
this.msg = msg;
this.timestamp = System.currentTimeMillis()/1000;
}
public Response(boolean state, int code, String msg, Object data) {
this.state = state;
this.code = code;
this.msg = msg;
this.data = data;
this.timestamp = System.currentTimeMillis()/1000;
}
public boolean isState() {
return state;
}
public void setState(boolean state) {
this.state = state;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
@Override
public String toString() {
return "Response{" +
"state=" + state +
", code=" + code +
", msg='" + msg + '\'' +
", data=" + data +
", timestamp=" + timestamp +
'}';
}
}
ResponseCode.java
package boot.example.tdengine.domain;
public class ResponseCode {
private static final boolean STATE_TRUE = true;
private static final boolean STATE_FALSE = false;
private static final int CODE_200 = 200; //操作资源成功
private static final int CODE_201 = 201; //资源为空
private static final int CORE_101 = 101; //缺少必要参数
private static final String MSG_ALL_SUCCESS = "操作资源成功";
private static final String MSG_PARAMETER_LACK = "缺少必要参数";
private static final String MSG_RESOURCES_EMPTY = "资源为空";
// 缺少必要参数返回
public static Response lackParameterResponse(){
return new Response(STATE_FALSE, CORE_101, MSG_PARAMETER_LACK);
}
// 通用success返回
public static Response successResponse(){
return new Response(STATE_TRUE,CODE_200,MSG_ALL_SUCCESS);
}
public static Response successResponse(Object data){
return new Response(STATE_TRUE,CODE_200,MSG_ALL_SUCCESS, data);
}
public static Response successEmptyResponse(){
return new Response(STATE_TRUE,CODE_201,MSG_RESOURCES_EMPTY);
}
}
DeviceEnvImeiMapper.java
package boot.example.tdengine.dao;
import boot.example.tdengine.domain.DeviceEnvImei;
import boot.example.tdengine.domain.DeviceEnvImeiRequestVo;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface DeviceEnvImeiMapper {
public void insertDeviceEnvImei(DeviceEnvImei deviceEnvImei);
public void insertBatchDeviceEnvImei(List<DeviceEnvImei> deviceEnvImeiList);
public List<DeviceEnvImei> listPageDeviceEnvImei(DeviceEnvImeiRequestVo deviceEnvImeiRequestVo);
public List<DeviceEnvImei> listDeviceEnvImei(DeviceEnvImeiRequestVo deviceEnvImeiRequestVo);
public int countDeviceEnvImei(DeviceEnvImeiRequestVo deviceEnvImeiRequestVo);
public void dropTableDeviceEnvImei(@Param("imei") String imei);
}
DeviceEnvImeiMapper.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="boot.example.tdengine.dao.DeviceEnvImeiMapper">
<resultMap id="baseResultMap" type="boot.example.tdengine.domain.DeviceEnvImei">
<id column="time_stamp" property="timeStamp"/>
<result column="imei" property="imei"/>
<result column="temp" property="temp"/>
<result column="hum" property="hum"/>
</resultMap>
<insert id="insertDeviceEnvImei" parameterType="boot.example.tdengine.domain.DeviceEnvImei">
INSERT INTO imei#{imei} USING device_env_imei (imei_point) TAGS (#{imei}) VALUES (#{timeStamp},#{imei},#{temp},#{hum})
</insert>
<insert id="insertBatchDeviceEnvImei" parameterType="java.util.List">
INSERT INTO
<foreach separator=" " collection="list" item="item" index="index">
imei#{item.imei} USING device_env_imei (imei_point) TAGS (#{item.imei}) VALUES (#{item.timeStamp},#{item.imei},#{item.temp},#{item.hum})
</foreach>
</insert>
<select id="countDeviceEnvImei" parameterType="boot.example.tdengine.domain.DeviceEnvImeiRequestVo" resultType="int">
select count(*) from imei#{imei}
<trim prefix="where" prefixOverrides="where" suffixOverrides="and">
<if test="startStamp != 0"><![CDATA[time_stamp > #{startStamp} and]]></if>
<if test="endStamp != 0"><![CDATA[time_stamp <= #{endStamp} and]]></if>
</trim>
</select>
<select id="listPageDeviceEnvImei" parameterType="boot.example.tdengine.domain.DeviceEnvImeiRequestVo" resultMap="baseResultMap">
select time_stamp, imei, temp, hum from imei#{imei}
<trim prefix="where" prefixOverrides="where" suffixOverrides="and">
<if test="startStamp != 0"><![CDATA[time_stamp > #{startStamp} and]]></if>
<if test="endStamp != 0"><![CDATA[time_stamp <= #{endStamp} and]]></if>
</trim>
order by time_stamp desc limit #{limit,jdbcType=BIGINT} offset #{offset,jdbcType=BIGINT}
</select>
<select id="listDeviceEnvImei" parameterType="boot.example.tdengine.domain.DeviceEnvImeiRequestVo" resultMap="baseResultMap">
select time_stamp, imei, temp, hum from imei#{imei}
<trim prefix="where" prefixOverrides="where" suffixOverrides="and">
<if test="startStamp != 0"><![CDATA[time_stamp > #{startStamp} and]]></if>
<if test="endStamp != 0"><![CDATA[time_stamp <= #{endStamp} and]]></if>
</trim>
order by time_stamp desc
</select>
<update id="dropTableDeviceEnvImei" parameterType="String">
drop table if exists imei#{imei}
</update>
</mapper>
DeviceEnvImeiService.java
package boot.example.tdengine.service;
import boot.example.tdengine.domain.DeviceEnvImei;
import boot.example.tdengine.domain.DeviceEnvImeiRequestVo;
import boot.example.tdengine.domain.Response;
import java.util.List;
public interface DeviceEnvImeiService {
public void insertDeviceEnvImeiService(DeviceEnvImei deviceEnvImei);
public Response listDeviceEnvImeiService(Long page, Long size, DeviceEnvImeiRequestVo deviceEnvImeiRequestVo);
public Response listDeviceEnvImeiService(DeviceEnvImeiRequestVo deviceEnvImeiRequestVo);
public void insertListDeviceEnvImeiService(List<DeviceEnvImei> list);
public void insertBatchDeviceEnvImei(List<DeviceEnvImei> deviceEnvImeiList);
public void dropDeviceEnvImeiService(String imei);
}
DeviceEnvImeiServiceImpl.java
package boot.example.tdengine.service;
import boot.example.tdengine.domain.Response;
import boot.example.tdengine.domain.ResponseCode;
import com.github.pagehelper.PageInfo;
import boot.example.tdengine.dao.DeviceEnvImeiMapper;
import boot.example.tdengine.domain.DeviceEnvImei;
import boot.example.tdengine.domain.DeviceEnvImeiRequestVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class DeviceEnvImeiServiceImpl implements DeviceEnvImeiService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Resource
private DeviceEnvImeiMapper deviceEnvImeiMapper;
@Async
@Override
public void insertDeviceEnvImeiService(DeviceEnvImei deviceEnvImei) {
try {
deviceEnvImeiMapper.insertDeviceEnvImei(deviceEnvImei);
} catch (Exception e){
log.error(e.toString());
}
}
@Override
public Response listDeviceEnvImeiService(Long page, Long size, DeviceEnvImeiRequestVo deviceEnvImeiRequestVo) {
long total = deviceEnvImeiMapper.countDeviceEnvImei(deviceEnvImeiRequestVo);
deviceEnvImeiRequestVo.setLimit(size);
deviceEnvImeiRequestVo.setOffset((page-1)*size);
List<DeviceEnvImei> eventList = deviceEnvImeiMapper.listPageDeviceEnvImei(deviceEnvImeiRequestVo);
PageInfo<DeviceEnvImei> pageInfo = new PageInfo<>(eventList);
pageInfo.setTotal(total);
return ResponseCode.successResponse(pageInfo);
}
@Override
public Response listDeviceEnvImeiService(DeviceEnvImeiRequestVo deviceEnvImeiRequestVo) {
List<DeviceEnvImei> eventList = deviceEnvImeiMapper.listDeviceEnvImei(deviceEnvImeiRequestVo);
if(!eventList.isEmpty()) {
return ResponseCode.successResponse(eventList);
}
return ResponseCode.successEmptyResponse();
}
@Async
@Override
public void insertListDeviceEnvImeiService(List<DeviceEnvImei> list) {
try {
for(DeviceEnvImei unified : list) {
deviceEnvImeiMapper.insertDeviceEnvImei(unified);
}
} catch (Exception e){
log.error(list.toString());
log.error(e.toString());
}
}
@Override
public void insertBatchDeviceEnvImei(List<DeviceEnvImei> deviceEnvImeiList) {
try {
deviceEnvImeiMapper.insertBatchDeviceEnvImei(deviceEnvImeiList);
} catch (Exception e){
//log.error(DeviceEnvImeiList.toString());
log.error(e.toString());
}
}
@Override
public void dropDeviceEnvImeiService(String imei) {
deviceEnvImeiMapper.dropTableDeviceEnvImei(imei);
}
}
DeviceEnvImeiController.java
package boot.example.tdengine.controller;
import boot.example.tdengine.domain.DeviceEnvImei;
import boot.example.tdengine.domain.DeviceEnvImeiRequestVo;
import boot.example.tdengine.domain.Response;
import boot.example.tdengine.domain.ResponseCode;
import boot.example.tdengine.service.DeviceEnvImeiService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@RequestMapping("/deviceEnv")
@Controller
public class DeviceEnvImeiController {
@Resource
private DeviceEnvImeiService deviceEnvImeiService;
@PostMapping("/listPage/{page}/{size}")
@ResponseBody
public Response listPageDeviceEnvImeiService(@PathVariable("page") Long page, @PathVariable("size") Long size, @RequestBody DeviceEnvImeiRequestVo deviceEnvImeiRequestVo){
if(page != null && page-1 >= 0 && deviceEnvImeiRequestVo.getImei() != null){
return deviceEnvImeiService.listDeviceEnvImeiService(page, size, deviceEnvImeiRequestVo);
}
return ResponseCode.lackParameterResponse();
}
@PostMapping("/list")
@ResponseBody
public Response listDeviceEnvImeiService(@RequestBody DeviceEnvImeiRequestVo deviceEnvImeiRequestVo){
if(deviceEnvImeiRequestVo.getImei() != null){
return deviceEnvImeiService.listDeviceEnvImeiService(deviceEnvImeiRequestVo);
}
return ResponseCode.lackParameterResponse();
}
@PostMapping("/drop/{imei}")
@ResponseBody
public Response dropDeviceEnvImeiService(@PathVariable("imei") String imei) {
deviceEnvImeiService.dropDeviceEnvImeiService(imei);
return ResponseCode.successResponse();
}
@PostMapping("/testData")
@ResponseBody
public Response test() {
DeviceEnvImei deviceEnvImei = new DeviceEnvImei();
deviceEnvImei.setTimeStamp(System.currentTimeMillis());
deviceEnvImei.setImei("90641");
deviceEnvImei.setTemp("18.88");
deviceEnvImei.setHum("45.6");
DeviceEnvImei deviceEnvImei2 = new DeviceEnvImei();
deviceEnvImei2.setTimeStamp(System.currentTimeMillis());
deviceEnvImei2.setImei("90641");
deviceEnvImei2.setTemp("18.88");
deviceEnvImei2.setHum("45.6");
List<DeviceEnvImei> list = new ArrayList<>();
list.add(deviceEnvImei);
list.add(deviceEnvImei2);
deviceEnvImeiService.insertBatchDeviceEnvImei(list);
DeviceEnvImei deviceEnvImei3 = new DeviceEnvImei();
deviceEnvImei3.setTimeStamp(System.currentTimeMillis());
deviceEnvImei3.setImei("90642");
deviceEnvImei3.setTemp("28.88");
deviceEnvImei3.setHum("65.6");
deviceEnvImeiService.insertDeviceEnvImeiService(deviceEnvImei3);
return ResponseCode.successResponse();
}
}
BootTdengineDemoMybatisApplication.java
package boot.example.tdengine;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan(basePackages = {"boot.example.tdengine.dao"})
@SpringBootApplication
public class BootTdengineDemoMybatisApplication {
public static void main(String[] args) {
SpringApplication.run(BootTdengineDemoMybatisApplication.class, args);
}
// 创建数据库
// create database td_device_log
// 创建超级表
// CREATE STABLE device_env_imei(time_stamp TIMESTAMP, imei varchar(64), temp varchar(64), hum varchar(64)) TAGS (imei_point varchar(64));
}
AsyncPoolTaskConfig.java
package boot.example.tdengine.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
@EnableAsync
@Configuration
public class AsyncPoolTaskConfig {
@Bean(name = "taskExecutor")
public ThreadPoolTaskExecutor getAsyncThreadPoolTaskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(30);
taskExecutor.setMaxPoolSize(50 * 2);
taskExecutor.setQueueCapacity(200);
taskExecutor.setKeepAliveSeconds(30);
taskExecutor.setThreadNamePrefix("ThreadPoolTaskExecutor-");
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
taskExecutor.setAwaitTerminationSeconds(60);
taskExecutor.initialize();
return taskExecutor;
}
}
SwaggerConfig.java
package boot.example.tdengine.config;
import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi(){
String defaultToken = "myyhtw";
ParameterBuilder headerToken = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
headerToken.name("token").description("token验证").modelRef(new ModelRef("string")).scalarExample(defaultToken).parameterType("header").required(false).build();
pars.add(headerToken.build());
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select()
.apis(RequestHandlerSelectors.any()).paths(PathSelectors.any())
.paths(Predicates.not(PathSelectors.regex("/error.*")))
.paths(PathSelectors.regex("/.*"))
.build().globalOperationParameters(pars).apiInfo(apiInfo());
}
private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("boot-example-mybatis-tdengine-接口")
.description("API接口文档")
.version("0.01")
.build();
}
}
目录结构
│ pom.xml
│
└─src
├─main
│ ├─java
│ │ └─boot
│ │ └─example
│ │ └─tdengine
│ │ │ BootTdengineDemoMybatisApplication.java
│ │ │
│ │ ├─config
│ │ │ AsyncPoolTaskConfig.java
│ │ │ BeanConfig.java
│ │ │ SwaggerConfig.java
│ │ │
│ │ ├─controller
│ │ │ DeviceEnvImeiController.java
│ │ │
│ │ ├─dao
│ │ │ DeviceEnvImeiMapper.java
│ │ │ DeviceEnvImeiMapper.xml
│ │ │
│ │ ├─domain
│ │ │ DeviceEnvImei.java
│ │ │ DeviceEnvImeiRequestVo.java
│ │ │ Response.java
│ │ │ ResponseCode.java
│ │ │
│ │ └─service
│ │ DeviceEnvImeiService.java
│ │ DeviceEnvImeiServiceImpl.java
│ │
│ └─resources
│ application.properties
│ logback-spring.xml
│
└─test
└─java
└─boot
└─example
└─tdengine
BootTdengineDemoMybatisApplicationTest.java