mirror of
https://github.com/taosdata/TDengine
synced 2026-05-24 10:09:01 +00:00
343 lines
13 KiB
Markdown
343 lines
13 KiB
Markdown
---
|
||
toc_max_heading_level: 4
|
||
sidebar_label: Java
|
||
title: TDengine Java Connector
|
||
description: TDengine Java 连接器基于标准 JDBC API 实现,并提供原生连接与 REST 连接两种连接器。
|
||
---
|
||
|
||
import Tabs from '@theme/Tabs';
|
||
import TabItem from '@theme/TabItem';
|
||
|
||
`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 连接无需安装),具体步骤请参考[安装客户端驱动](https://docs.taosdata.com/reference/connector/#%E5%AE%89%E8%A3%85%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%A9%B1%E5%8A%A8)
|
||
|
||
### 安装连接器
|
||
|
||
<Tabs defaultValue="maven">
|
||
<TabItem value="maven" label="使用 Maven 安装">
|
||
|
||
目前 taos-jdbcdriver 已经发布到 [Sonatype Repository](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver) 仓库,且各大仓库都已同步。
|
||
|
||
- [sonatype](https://search.maven.org/artifact/com.taosdata.jdbc/taos-jdbcdriver)
|
||
- [mvnrepository](https://mvnrepository.com/artifact/com.taosdata.jdbc/taos-jdbcdriver)
|
||
- [maven.aliyun](https://maven.aliyun.com/mvn/search)
|
||
|
||
Maven 项目中,在 pom.xml 中添加以下依赖:
|
||
|
||
```xml-dtd
|
||
<dependency>
|
||
<groupId>com.taosdata.jdbc</groupId>
|
||
<artifactId>taos-jdbcdriver</artifactId>
|
||
<version>3.2.7</version>
|
||
</dependency>
|
||
```
|
||
|
||
</TabItem>
|
||
<TabItem value="source" label="使用源码编译安装">
|
||
|
||
可以通过下载 TDengine 的源码,自己编译最新版本的 Java connector
|
||
|
||
```shell
|
||
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 仓库中。
|
||
|
||
</TabItem>
|
||
</Tabs>
|
||
|
||
## 建立连接
|
||
|
||
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}`
|
||
|
||
```java
|
||
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);
|
||
```
|
||
|
||
:::note IMPORTANT
|
||
|
||
- REST 接口是无状态的。在使用 JDBC REST 连接时,需要在 SQL 中指定表、超级表的数据库名称。例如:
|
||
|
||
```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:
|
||
|
||
```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。
|
||
|
||
```java
|
||
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、客户端配置文件中有重复,则参数的`优先级由高到低`分别如下:
|
||
|
||
1. JDBC URL 参数,如上所述,可以在 JDBC URL 的参数中指定。
|
||
2. Properties connProps
|
||
|
||
## 使用示例
|
||
|
||
### 创建数据库和表
|
||
|
||
```java
|
||
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)");
|
||
```
|
||
|
||
### 插入数据
|
||
|
||
```java
|
||
// 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(年)。
|
||
|
||
### 查询数据
|
||
|
||
```java
|
||
// 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 可以获取到错误的信息和错误码:
|
||
|
||
```java
|
||
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 其他功能模块的报错。
|
||
|
||
具体的错误码请参考:
|
||
|
||
- [TDengine Java Connector](https://github.com/taosdata/taos-connector-jdbc/blob/main/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java)
|
||
|
||
### 关闭资源
|
||
|
||
```java
|
||
resultSet.close();
|
||
stmt.close();
|
||
conn.close();
|
||
```
|
||
|
||
:::note IMPORTANT
|
||
请确保关闭连接,否则会造成连接池泄露。
|
||
:::
|
||
|
||
### 与连接池使用
|
||
|
||
#### HikariCP
|
||
|
||
使用示例如下:
|
||
|
||
```java
|
||
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 使用问题请查看[官方说明](https://github.com/brettwooldridge/HikariCP)。
|
||
|
||
#### Druid
|
||
|
||
使用示例如下:
|
||
|
||
```java
|
||
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 使用问题请查看[官方说明](https://github.com/alibaba/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](https://github.com/taosdata/TDengine/tree/3.0/examples/JDBC)
|
||
|
||
## 最近更新记录
|
||
|
||
| 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 写入支持 |
|
||
|
||
## 常见问题
|
||
|
||
1. 使用 Statement 的 `addBatch()` 和 `executeBatch()` 来执行“批量写入/更新”,为什么没有带来性能上的提升?
|
||
|
||
**原因**:TDengine 的 JDBC 实现中,通过 `addBatch` 方法提交的 SQL 语句,会按照添加的顺序,依次执行,这种方式没有减少与服务端的交互次数,不会带来性能上的提升。
|
||
|
||
**解决方法**:1. 在一条 insert 语句中拼接多个 values 值;2. 使用多线程的方式并发插入;3. 使用参数绑定的写入方式
|
||
|
||
2. 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`。
|
||
|
||
3. java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform
|
||
|
||
**原因**:目前 TDengine 只支持 64 位 JDK。
|
||
|
||
**解决方法**:重新安装 64 位 JDK。
|
||
|
||
4. java.lang.NoSuchMethodError: setByteArray
|
||
|
||
**原因**:taos-jdbcdriver 3.* 版本仅支持 TDengine 3.0 及以上版本。
|
||
|
||
**解决方法**:使用 taos-jdbcdriver 2.*版本连接 TDengine 2.* 版本。
|
||
|
||
5. java.lang.NoSuchMethodError: java.nio.ByteBuffer.position(I)Ljava/nio/ByteBuffer; ... taos-jdbcdriver-3.0.1.jar
|
||
|
||
**原因**:taos-jdbcdriver 3.0.1 版本需要在 JDK 11+ 环境使用。
|
||
|
||
## API 参考
|
||
|
||
[taos-jdbcdriver doc](https://docs.taosdata.com/api/taos-jdbcdriver)
|