TDengine Java Connector
taos-jdbcdriver
是 TDengine 的官方 Java 语言连接器,Java 开发人员可以通过它开发存取 TDengine 数据库 的应用软件。taos-jdbcdriver
实现了 JDBC driver 标准的接口,通过 REST 接口连接 TDengine 实例。
TDengine DataType 和 Java DataType
TDengine 目前支持时间戳、数字、字符、布尔类型,与 Java 对应类型转换如下:
TDengine DataType | JDBCType |
---|---|
TIMESTAMP | java.sql.Timestamp |
INT | java.lang.Integer |
BIGINT | java.lang.Long |
FLOAT | java.lang.Float |
DOUBLE | java.lang.Double |
SMALLINT | java.lang.Short |
TINYINT | java.lang.Byte |
BOOL | java.lang.Boolean |
BINARY | byte array |
NCHAR | java.lang.String |
JSON | java.lang.String |
注意:JSON 类型仅在 tag 中支持。
安装步骤
安装前准备
使用 Java Connector 连接数据库前,需要具备以下条件:
- 已安装 Java 1.8 或以上版本运行时环境和 Maven 3.6 或以上版本
- 已安装 TDengine 客户端驱动(使用原生连接必须安装,使用 REST 连接无需安装),具体步骤请参考安装客户端驱动
安装连接器
- 使用 Maven 安装
- 使用源码编译安装
目前 taos-jdbcdriver 已经发布到 Sonatype Repository 仓库,且各大仓库都已同步。
Maven 项目中,在 pom.xml 中添加以下依赖:
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>3.2.7</version>
</dependency>
可以通过下载 TDengine 的源码,自己编译最新版本的 Java connector
git clone https://github.com/taosdata/taos-connector-jdbc.git
cd taos-connector-jdbc
mvn clean install -Dmaven.test.skip=true
编译后,在 target 目录下会产生 taos-jdbcdriver-3.0.*-dist.jar 的 jar 包,并自动将编译的 jar 文件放在本地的 Maven 仓库中。
建立连接
TDengine 的 JDBC URL 规范格式为:
jdbc:TAOS-RS://[host_name]:[port]/[database_name]?batchfetch={true|false}&useSSL={true|false}&token={token}&httpPoolSize={httpPoolSize}&httpKeepAlive={true|false}]&httpConnectTimeout={httpTimeout}&httpSocketTimeout={socketTimeout}
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
String jdbcUrl = "jdbc:TAOS-RS://taosdemo.com:6041/test?user=root&password=taosdata";
Connection conn = DriverManager.getConnection(jdbcUrl);
- REST 接口是无状态的。在使用 JDBC REST 连接时,需要在 SQL 中指定表、超级表的数据库名称。例如:
INSERT INTO test.t1 USING test.weather (ts, temperature) TAGS('California.SanFrancisco') VALUES(now, 24.6);
-
如果在 URL 中指定了 dbname,那么 JDBC REST 连接会默认使用
/rest/sql/dbname
作为 restful 请求的 URL,在 SQL 中不需要指定 dbname。例如:URL 为 jdbc:TAOS-RS://127.0.0.1:6041/test,那么,可以执行 SQL:insert into t1 using weather(ts, temperature) tags('California.SanFrancisco') values(now, 24.6);
指定 URL 和 Properties 获取连接
除了通过指定的 URL 获取连接,还可以使用 Properties 指定建立连接时的参数。
注意:
- 应用中设置的 client parameter 为进程级别的,即如果要更新 client 的参数,需要重启应用。这是因为 client parameter 是全局参数,仅在应用程序的第一次设置生效。
- 以下示例代码基于 taos-jdbcdriver-3.0.0。
public Connection getRestConn() throws Exception{
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
String jdbcUrl = System.getenv("TDENGINE_JDBC_URL");
Properties connProps = new Properties();
connProps.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true");
Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
return conn;
}
配置参数的优先级
通过前面三种方式获取连接,如果配置参数在 url、Properties、客户端配置文件中有重复,则参数的优先级由高到低
分别如下:
- JDBC URL 参数,如上所述,可以在 JDBC URL 的参数中指定。
- Properties connProps
使用示例
创建数据库和表
Statement stmt = conn.createStatement();
// create database
stmt.executeUpdate("create database if not exists db");
// use database
stmt.executeUpdate("use db");
// create table
stmt.executeUpdate("create table if not exists tb (ts timestamp, temperature int, humidity float)");
插入数据
// insert data
int affectedRows = stmt.executeUpdate("insert into tb values(now, 23, 10.3) (now + 1s, 20, 9.3)");
System.out.println("insert " + affectedRows + " rows.");
now
为系统内部函数,默认为客户端所在计算机当前时间。now + 1s
代表客户端当前时间往后加 1 秒,数字后面代表时间单位:a(毫秒),s(秒),m(分),h(小时),d(天),w(周),n(月),y(年)。
查询数据
// query data
ResultSet resultSet = stmt.executeQuery("select * from tb");
Timestamp ts = null;
int temperature = 0;
float humidity = 0;
while(resultSet.next()){
ts = resultSet.getTimestamp(1);
temperature = resultSet.getInt(2);
humidity = resultSet.getFloat("humidity");
System.out.printf("%s, %d, %s\n", ts, temperature, humidity);
}
查询和操作关系型数据库一致,使用下标获取返回字 段内容时从 1 开始,建议使用字段名称获取。
处理异常
在报错后,通过 SQLException 可以获取到错误的信息和错误码:
try (Statement statement = connection.createStatement()) {
// executeQuery
ResultSet resultSet = statement.executeQuery(sql);
// print result
printResult(resultSet);
} catch (SQLException e) {
System.out.println("ERROR Message: " + e.getMessage());
System.out.println("ERROR Code: " + e.getErrorCode());
e.printStackTrace();
}
JDBC 连接器可能报错的错误码包括 3 种:JDBC driver 本身的报错(错误码在 0x2301 到 0x2350 之间),原生连接方法的报错(错误码在 0x2351 到 0x2400 之间),TDengine 其他功能模块的报错。
具体的错误码请参考:
关闭资源
resultSet.close();
stmt.close();
conn.close();
请确保关闭连接,否则会造成连接池泄露。
与连接池使用
HikariCP
使用示例如下:
public static void main(String[] args) throws SQLException {
HikariConfig config = new HikariConfig();
// jdbc properties
config.setJdbcUrl("jdbc:TAOS://127.0.0.1:6030/log");
config.setUsername("root");
config.setPassword("taosdata");
// connection pool configurations
config.setMinimumIdle(10); //minimum number of idle connection
config.setMaximumPoolSize(10); //maximum number of connection in the pool
config.setConnectionTimeout(30000); //maximum wait milliseconds for get connection from pool
config.setMaxLifetime(0); // maximum life time for each connection
config.setIdleTimeout(0); // max idle time for recycle idle connection
config.setConnectionTestQuery("select server_status()"); //validation query
HikariDataSource ds = new HikariDataSource(config); //create datasource
Connection connection = ds.getConnection(); // get connection
Statement statement = connection.createStatement(); // get statement
//query or insert
// ...
connection.close(); // put back to connection pool
}
通过 HikariDataSource.getConnection() 获取连接后,使用完成后需要调用 close() 方法,实际上它并不会关闭连接,只是放回连接池中。 更多 HikariCP 使用问题请查看官方说明。
Druid
使用示例如下:
public static void main(String[] args) throws Exception {
DruidDataSource dataSource = new DruidDataSource();
// jdbc properties
dataSource.setDriverClassName("com.taosdata.jdbc.TSDBDriver");
dataSource.setUrl(url);
dataSource.setUsername("root");
dataSource.setPassword("taosdata");
// pool configurations
dataSource.setInitialSize(10);
dataSource.setMinIdle(10);
dataSource.setMaxActive(10);
dataSource.setMaxWait(30000);
dataSource.setValidationQuery("select server_status()");
Connection connection = dataSource.getConnection(); // get connection
Statement statement = connection.createStatement(); // get statement
//query or insert
// ...
connection.close(); // put back to connection pool
}
更多 druid 使用问题请查看官方说明。
更多示例程序
示例程序源码位于 TDengine/examples/JDBC
下:
- JDBCDemo:JDBC 示例源程序。
- JDBCConnectorChecker:JDBC 安装校验源程序及 jar 包。
- connectionPools:HikariCP, Druid, dbcp, c3p0 等连接池中使用 taos-jdbcdriver。
- SpringJdbcTemplate:Spring JdbcTemplate 中使用 taos-jdbcdriver。
- mybatisplus-demo:Springboot + Mybatis 中使用 taos-jdbcdriver。
请参考:JDBC example
最近更新记录
taos-jdbcdriver 版本 | 主要变化 |
---|---|
3.0.3 | 修复 REST 连接在 jdk17+ 版本时间戳解析错误问题 |
3.0.1 - 3.0.2 | 修复一些情况下结果集数据解析错误的问题。3.0.1 在 JDK 11 环境编译,JDK 8 环境下建议使用 3.0.2 版本 |
3.0.0 | 支持 TDengine 3.0 |
2.0.42 | 修在 WebSocket 连接中 wasNull 接口返回值 |
2.0.41 | 修正 REST 连接中用户名和密码转码方式 |
2.0.39 - 2.0.40 | 增加 REST 连接/请求 超时设置 |
2.0.38 | JDBC REST 连接增加批量拉取功能 |
2.0.37 | 增加对 json tag 支持 |
2.0.36 | 增加对 schemaless 写入支持 |
常见问题
- 使用 Statement 的
addBatch()
和executeBatch()
来执行“批量写入/更新”,为什么没有带来性能上的提升?
原因:TDengine 的 JDBC 实现中,通过 addBatch
方法提交的 SQL 语句,会按照添加的顺序,依次执行,这种方式没有减少与服务端的交互次数,不会带来性能上的提升。
解决方法:1. 在一条 insert 语句中拼接多个 values 值;2. 使用多线程的方式并发插入;3. 使用参数绑定的写入方式
- java.lang.UnsatisfiedLinkError: no taos in java.library.path
原因:程序没有找到依赖的本地函数库 taos。
解决方法:Windows 下可以将 C:\TDengine\driver\taos.dll 拷贝到 C:\Windows\System32\ 目录下,Linux 下将建立如下软链 ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so
即可,macOS 下需要建立软链 ln -s /usr/local/lib/libtaos.dylib
。
- java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform
原因:目前 TDengine 只支持 64 位 JDK。
解决方法:重新安装 64 位 JDK。
- java.lang.NoSuchMethodError: setByteArray
原因:taos-jdbcdriver 3.* 版本仅支持 TDengine 3.0 及以上版本。
解决方法: 使用 taos-jdbcdriver 2.* 版本连接 TDengine 2.* 版本。
- java.lang.NoSuchMethodError: java.nio.ByteBuffer.position(I)Ljava/nio/ByteBuffer; ... taos-jdbcdriver-3.0.1.jar
原因:taos-jdbcdriver 3.0.1 版本需要在 JDK 11+ 环境使用。