环境准备
- 服务端(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方式
准备
- linux或windows操作系统
- java 1.8以上运行时环境
- 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</groupid> <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.38 | x | x | 2.4.0.14 及以上 | 1.8.x |
2.0.37 | x | x | 2.4.0.6 及以上 | 1.8.x |
2.0.36 | x | 2.2.2.11 及以上 | 2.4.0.0 - 2.4.0.5 | 1.8.x |
2.0.35 | x | 2.2.2.11 及以上 | 2.3.0.0 - 2.4.0.5 | 1.8.x |
2.0.33 - 2.0.34 | 2.0.3.0 及以上 | 2.2.0.0 及以上 | 2.4.0.0 - 2.4.0.5 | 1.8.x |
2.0.31 - 2.0.32 | 2.1.3.0 - 2.1.7.7 | x | x | 1.8.x |
2.0.22 - 2.0.30 | 2.0.18.0 - 2.1.2.1 | x | x | 1.8.x |
2.0.12 - 2.0.21 | 2.0.8.0 - 2.0.17.4 | x | x | 1.8.x |
2.0.4 - 2.0.11 | 2.0.0.0 - 2.0.7.3 | x | x | 1.8.x |
实体类
@data public class temperature { private timestamp ts; private float temperature; private string location; private int tbindex; }
tdengine 类型对应java类型
tdengine 目前支持时间戳、数字、字符、布尔类型,与 java 对应类型转换如下
tdengine datatype | jdbctype (driver 版本 < 2.0.24) | jdbctype (driver 版本 >= 2.0.24) |
---|---|---|
timestamp | java.lang.long | java.sql.timestamp |
int | java.lang.integer | java.lang.integer |
bigint | java.lang.long | java.lang.long |
float | java.lang.float | java.lang.float |
double | java.lang.double | java.lang.double |
smallint | java.lang.short | java.lang.short |
tinyint | java.lang.byte | java.lang.byte |
bool | java.lang.boolean | java.lang.boolean |
binary | java.lang.string | byte array |
nchar | java.lang.string | java.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); } /** * 分页查询 */ @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.weather (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("note-" + 1); //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”
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论