714 lines
43 KiB
Plaintext
714 lines
43 KiB
Plaintext
---
|
||
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';
|
||
import RequestId from "./_request_id.mdx";
|
||
|
||
`taos-jdbcdriver` 是 TDengine 的官方 Java 语言连接器,Java 开发人员可以通过它开发存取 TDengine 数据库的应用软件。`taos-jdbcdriver` 实现了 JDBC driver 标准的接口.
|
||
|
||
:::info
|
||
TDengine 的 JDBC 驱动实现尽可能与关系型数据库驱动保持一致,但 TDengine 与关系对象型数据库的使用场景和技术特征存在差异,所以`taos-jdbcdriver` 与传统的 JDBC driver 也存在一定差异。在使用时需要注意以下几点:
|
||
|
||
- TDengine 目前不支持针对单条数据记录的删除操作。
|
||
- 目前不支持事务操作。
|
||
|
||
:::
|
||
|
||
## 连接方式
|
||
`taos-jdbcdriver`主要提供三种形式的连接器。一般我们推荐使用 **Websocket 连接**。
|
||
- **原生连接**,通过 TDengine 客户端驱动程序(taosc)原生连接 TDengine 实例,支持数据写入、查询、数据订阅、schemaless 接口和参数绑定接口等功能。
|
||
- **REST 连接**,通过 taosAdapter 提供的 HTTP 接口连接 TDengine 实例,不支持 schemaless 和数据订阅等特性。
|
||
- **Websocket 连接**,通过 taosAdapter 提供的 Websocket 接口连接 TDengine 实例,WebSocket 连接实现的功能集合和原生连接有少量不同。
|
||
|
||
连接方式的详细介绍请参考:[连接器建立连接的方式](../../develop/connect/#连接器建立连接的方式)
|
||
|
||
## JDBC 和 JRE 兼容性
|
||
|
||
- JDBC: 支持 JDBC 4.2 版本,部分功能如无模式写入和数据订阅单独提供
|
||
- JRE: 支持 JRE 8 及以上版本
|
||
|
||
## 支持的平台
|
||
|
||
原生连接支持的平台和 TDengine 客户端驱动支持的平台一致。
|
||
REST 连接支持所有能运行 Java 的平台。
|
||
|
||
## 版本历史
|
||
|
||
| taos-jdbcdriver 版本 | 主要变化 | TDengine 版本 |
|
||
| :------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------: |
|
||
| 3.3.0 | 1. 优化 Websocket 连接下的数据传输性能;2. 支持跳过 SSL 验证,默认关闭 | 3.3.2.0 及更高版本 |
|
||
| 3.2.11 | 解决了 Native 连接关闭结果集 bug | - |
|
||
| 3.2.10 | 1. REST/WebSocket 连接支持传输中的数据压缩;2. Websocket 自动重连机制,默认关闭;3. Connection 类提供无模式写入的方法;4. 优化了原生连接的数据拉取性能;5. 修复了一些已知问题;6.元数据获取函数可以返回支持的函数列表。 | - |
|
||
| 3.2.9 | 解决了 Websocket prepareStatement 关闭 bug | - |
|
||
| 3.2.8 | 优化了自动提交, 解决了 websocket 手动提交 bug, 优化 Websocket prepareStatement 使用一个连接, 元数据支持视图 | - |
|
||
| 3.2.7 | 支持 VARBINARY 和 GEOMETRY 类型,增加 native 连接的时区设置支持。增加 websocket 自动重连功能。 | 3.2.0.0 及更高版本 |
|
||
| 3.2.5 | 数据订阅增加 committed()、assignment() 方法 | 3.1.0.3 及更高版本 |
|
||
| 3.2.4 | 数据订阅在 WebSocket 连接下增加 enable.auto.commit 参数,以及 unsubscribe() 方法。 | - |
|
||
| 3.2.3 | 修复 ResultSet 在一些情况数据解析失败 | - |
|
||
| 3.2.2 | 新增功能:数据订阅支持 seek 功能。 | 3.0.5.0 及更高版本 |
|
||
| 3.2.1 | 新增功能:WebSocket 连接支持 schemaless 与 prepareStatement 写入。变更:consumer poll 返回结果集为 ConsumerRecord,可通过 value() 获取指定结果集数据。 | 3.0.3.0 及更高版本 |
|
||
| 3.2.0 | 存在连接问题,不推荐使用 | - |
|
||
| 3.1.0 | WebSocket 连接支持订阅功能 | - |
|
||
| 3.0.1 - 3.0.4 | 修复一些情况下结果集数据解析错误的问题。3.0.1 在 JDK 11 环境编译,JDK 8 环境下建议使用其他版本 | - |
|
||
| 3.0.0 | 支持 TDengine 3.0 | 3.0.0.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 写入支持 | - |
|
||
|
||
## 处理异常
|
||
|
||
在报错后,通过 SQLException 可以获取到错误的信息和错误码:
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JdbcBasicDemo.java:jdbc_exception}}
|
||
```
|
||
|
||
JDBC 连接器可能报错的错误码包括 4 种:
|
||
|
||
- JDBC driver 本身的报错(错误码在 0x2301 到 0x2350 之间)
|
||
- 原生连接方法的报错(错误码在 0x2351 到 0x2360 之间)
|
||
- 数据订阅的报错(错误码在 0x2371 到 0x2380 之间)
|
||
- TDengine 其他功能模块的报错。
|
||
|
||
具体的错误码请参考:
|
||
|
||
| Error Code | Description | Suggested Actions |
|
||
| ---------- | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||
| 0x2301 | connection already closed | 连接已经关闭,检查连接情况,或重新创建连接去执行相关指令。 |
|
||
| 0x2302 | this operation is NOT supported currently! | 当前使用接口不支持,可以更换其他连接方式。 |
|
||
| 0x2303 | invalid variables | 参数不合法,请检查相应接口规范,调整参数类型及大小。 |
|
||
| 0x2304 | statement is closed | statement 已经关闭,请检查 statement 是否关闭后再次使用,或是连接是否正常。 |
|
||
| 0x2305 | resultSet is closed | resultSet 结果集已经释放,请检查 resultSet 是否释放后再次使用。 |
|
||
| 0x2306 | Batch is empty! | prepareStatement 添加参数后再执行 executeBatch。 |
|
||
| 0x2307 | Can not issue data manipulation statements with executeQuery() | 更新操作应该使用 executeUpdate(),而不是 executeQuery()。 |
|
||
| 0x2308 | Can not issue SELECT via executeUpdate() | 查询操作应该使用 executeQuery(),而不是 executeUpdate()。 |
|
||
| 0x230d | parameter index out of range | 参数越界,请检查参数的合理范围。 |
|
||
| 0x230e | connection already closed | 连接已经关闭,请检查 Connection 是否关闭后再次使用,或是连接是否正常。 |
|
||
| 0x230f | unknown sql type in tdengine | 请检查 TDengine 支持的 Data Type 类型。 |
|
||
| 0x2310 | can't register JDBC-JNI driver | 不能注册 JNI 驱动,请检查 url 是否填写正确。 |
|
||
| 0x2312 | url is not set | 请检查 REST 连接 url 是否填写正确。 |
|
||
| 0x2314 | numeric value out of range | 请检查获取结果集中数值类型是否使用了正确的接口。 |
|
||
| 0x2315 | unknown taos type in tdengine | 在 TDengine 数据类型与 JDBC 数据类型转换时,是否指定了正确的 TDengine 数据类型。 |
|
||
| 0x2317 | | REST 连接中使用了错误的请求类型。 |
|
||
| 0x2318 | | REST 连接中出现了数据传输异常,请检查网络情况并重试。 |
|
||
| 0x2319 | user is required | 创建连接时缺少用户名信息 |
|
||
| 0x231a | password is required | 创建连接时缺少密码信息 |
|
||
| 0x231c | httpEntity is null, sql: | REST 连接中执行出现异常 |
|
||
| 0x231d | can't create connection with server within | 通过增加参数 httpConnectTimeout 增加连接耗时,或是请检查与 taosAdapter 之间的连接情况。 |
|
||
| 0x231e | failed to complete the task within the specified time | 通过增加参数 messageWaitTimeout 增加执行耗时,或是请检查与 taosAdapter 之间的连接情况。 |
|
||
| 0x2350 | unknown error | 未知异常,请在 github 反馈给开发人员。 |
|
||
| 0x2352 | Unsupported encoding | 本地连接下指定了不支持的字符编码集 |
|
||
| 0x2353 | internal error of database, please see taoslog for more details | 本地连接执行 prepareStatement 时出现错误,请检查 taos log 进行问题定位。 |
|
||
| 0x2354 | JNI connection is NULL | 本地连接执行命令时,Connection 已经关闭。请检查与 TDengine 的连接情况。 |
|
||
| 0x2355 | JNI result set is NULL | 本地连接获取结果集,结果集异常,请检查连接情况,并重试。 |
|
||
| 0x2356 | invalid num of fields | 本地连接获取结果集的 meta 信息不匹配。 |
|
||
| 0x2357 | empty sql string | 填写正确的 SQL 进行执行。 |
|
||
| 0x2359 | JNI alloc memory failed, please see taoslog for more details | 本地连接分配内存错误,请检查 taos log 进行问题定位。 |
|
||
| 0x2371 | consumer properties must not be null! | 创建订阅时参数为空,请填写正确的参数。 |
|
||
| 0x2372 | configs contain empty key, failed to set consumer property | 参数 key 中包含空值,请填写正确的参数。 |
|
||
| 0x2373 | failed to set consumer property, | 参数 value 中包含空值,请填写正确的参数。 |
|
||
| 0x2375 | topic reference has been destroyed | 创建数据订阅过程中,topic 引用被释放。请检查与 TDengine 的连接情况。 |
|
||
| 0x2376 | failed to set consumer topic, topic name is empty | 创建数据订阅过程中,订阅 topic 名称为空。请检查指定的 topic 名称是否填写正确。 |
|
||
| 0x2377 | consumer reference has been destroyed | 订阅数据传输通道已经关闭,请检查与 TDengine 的连接情况。 |
|
||
| 0x2378 | consumer create error | 创建数据订阅失败,请根据错误信息检查 taos log 进行问题定位。 |
|
||
| 0x2379 | seek offset must not be a negative number | seek 接口参数不能为负值,请使用正确的参数 |
|
||
| 0x237a | vGroup not found in result set | VGroup 没有分配给当前 consumer,由于 Rebalance 机制导致 Consumer 与 VGroup 不是绑定的关系 |
|
||
|
||
- [TDengine Java Connector Error Code](https://github.com/taosdata/taos-connector-jdbc/blob/main/src/main/java/com/taosdata/jdbc/TSDBErrorNumbers.java)
|
||
<!-- - [TDengine_ERROR_CODE](../error-code) -->
|
||
|
||
## 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 |
|
||
| VARBINARY | byte[] |
|
||
| GEOMETRY | byte[] |
|
||
|
||
**注意**:JSON 类型仅在 tag 中支持。
|
||
由于历史原因,TDengine中的BINARY底层不是真正的二进制数据,已不建议使用。请用VARBINARY类型代替。
|
||
GEOMETRY类型是little endian字节序的二进制数据,符合WKB规范。详细信息请参考 [数据类型](../../taos-sql/data-type/#数据类型)
|
||
WKB规范请参考[Well-Known Binary (WKB)](https://libgeos.org/specifications/wkb/)
|
||
对于java连接器,可以使用jts库来方便的创建GEOMETRY类型对象,序列化后写入TDengine,这里有一个样例[Geometry示例](https://github.com/taosdata/TDengine/blob/3.0/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/GeometryDemo.java)
|
||
|
||
## 安装步骤
|
||
|
||
### 安装前准备
|
||
|
||
使用 Java Connector 连接数据库前,需要具备以下条件:
|
||
|
||
- 已安装 Java 1.8 或以上版本运行时环境和 Maven 3.6 或以上版本
|
||
- 已安装 TDengine 客户端驱动(使用原生连接必须安装,使用 REST 连接无需安装),具体步骤请参考[安装客户端驱动](../#安装客户端驱动)
|
||
|
||
### 安装连接器
|
||
|
||
<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.3.0</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.2.\*-dist.jar 的 jar 包,并自动将编译的 jar 文件放在本地的 Maven 仓库中。
|
||
|
||
</TabItem>
|
||
</Tabs>
|
||
|
||
## 建立连接
|
||
|
||
TDengine 的 JDBC URL 规范格式为:
|
||
`jdbc:[TAOS|TAOS-RS]://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
|
||
|
||
对于建立连接,原生连接与 REST 连接有细微不同。
|
||
|
||
**注**:REST 连接中增加 `batchfetch` 参数并设置为 true,将开启 WebSocket 连接。
|
||
|
||
<Tabs defaultValue="rest">
|
||
<TabItem value="native" label="原生连接">
|
||
|
||
```java
|
||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
||
String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/power?user=root&password=taosdata";
|
||
Connection conn = DriverManager.getConnection(jdbcUrl);
|
||
```
|
||
|
||
以上示例,使用了 JDBC 原生连接的 TSDBDriver,建立了到 hostname 为 taosdemo.com,端口为 6030(TDengine 的默认端口),数据库名为 power 的连接。这个 URL
|
||
中指定用户名(user)为 root,密码(password)为 taosdata。
|
||
|
||
**注意**:使用 JDBC 原生连接,taos-jdbcdriver 需要依赖客户端驱动(Linux 下是 libtaos.so;Windows 下是 taos.dll;macOS 下是 libtaos.dylib)。
|
||
|
||
url 中的配置参数如下:
|
||
|
||
- user:登录 TDengine 用户名,默认值 'root'。
|
||
- password:用户登录密码,默认值 'taosdata'。
|
||
- cfgdir:客户端配置文件目录路径,Linux OS 上默认值 `/etc/taos`,Windows OS 上默认值 `C:/TDengine/cfg`。
|
||
- charset:客户端使用的字符集,默认值为系统字符集。
|
||
- locale:客户端语言环境,默认值系统当前 locale。
|
||
- timezone:客户端使用的时区,默认值为系统当前时区。
|
||
- batchfetch: true:在执行查询时批量拉取结果集;false:逐行拉取结果集。默认值为:true。开启批量拉取同时获取一批数据在查询数据量较大时批量拉取可以有效的提升查询性能。
|
||
- batchErrorIgnore:true:在执行 Statement 的 executeBatch 时,如果中间有一条 SQL 执行失败将继续执行下面的 SQL。false:不再执行失败 SQL 后的任何语句。默认值为:false。
|
||
|
||
JDBC 原生连接的使用请参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1955.html)。
|
||
|
||
**使用 TDengine 客户端驱动配置文件建立连接 **
|
||
|
||
当使用 JDBC 原生连接连接 TDengine 集群时,可以使用 TDengine 客户端驱动配置文件,在配置文件中指定集群的 firstEp、secondEp 等参数。如下所示:
|
||
|
||
1. 在 Java 应用中不指定 hostname 和 port
|
||
|
||
```java
|
||
public Connection getConn() throws Exception{
|
||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
||
String jdbcUrl = "jdbc:TAOS://:/power?user=root&password=taosdata";
|
||
Properties connProps = new Properties();
|
||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||
Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
|
||
return conn;
|
||
}
|
||
```
|
||
|
||
2. 在配置文件中指定 firstEp 和 secondEp
|
||
|
||
```shell
|
||
# first fully qualified domain name (FQDN) for TDengine system
|
||
firstEp cluster_node1:6030
|
||
|
||
# second fully qualified domain name (FQDN) for TDengine system, for cluster only
|
||
secondEp cluster_node2:6030
|
||
|
||
# default system charset
|
||
# charset UTF-8
|
||
|
||
# system locale
|
||
# locale en_US.UTF-8
|
||
```
|
||
|
||
以上示例,jdbc 会使用客户端的配置文件,建立到 hostname 为 cluster_node1、端口为 6030、数据库名为 power 的连接。当集群中 firstEp 节点失效时,JDBC 会尝试使用 secondEp 连接集群。
|
||
|
||
TDengine 中,只要保证 firstEp 和 secondEp 中一个节点有效,就可以正常建立到集群的连接。
|
||
|
||
> **注意**:这里的配置文件指的是调用 JDBC Connector 的应用程序所在机器上的配置文件,Linux OS 上默认值 /etc/taos/taos.cfg ,Windows OS 上默认值 C://TDengine/cfg/taos.cfg。
|
||
|
||
</TabItem>
|
||
<TabItem value="rest" label="REST 连接">
|
||
|
||
```java
|
||
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
|
||
String jdbcUrl = "jdbc:TAOS-RS://taosdemo.com:6041/power?user=root&password=taosdata";
|
||
Connection conn = DriverManager.getConnection(jdbcUrl);
|
||
```
|
||
|
||
以上示例,使用了 JDBC REST 连接的 RestfulDriver,建立了到 hostname 为 taosdemo.com,端口为 6041,数据库名为 power 的连接。这个 URL 中指定用户名(user)为 root,密码(password)为 taosdata。
|
||
|
||
使用 JDBC REST 连接,不需要依赖客户端驱动。与 JDBC 原生连接相比,仅需要:
|
||
|
||
1. driverClass 指定为“com.taosdata.jdbc.rs.RestfulDriver”;
|
||
2. jdbcUrl 以“jdbc:TAOS-RS://”开头;
|
||
3. 使用 6041 作为连接端口。
|
||
|
||
url 中的配置参数如下:
|
||
|
||
- user:登录 TDengine 用户名,默认值 'root'。
|
||
- password:用户登录密码,默认值 'taosdata'。
|
||
- batchfetch: true:在执行查询时批量拉取结果集;false:逐行拉取结果集。默认值为:false。逐行拉取结果集使用 HTTP 方式进行数据传输。JDBC REST 连接支持批量拉取数据功能。taos-jdbcdriver 与 TDengine 之间通过 WebSocket 连接进行数据传输。相较于 HTTP,WebSocket 可以使 JDBC REST 连接支持大数据量查询,并提升查询性能。
|
||
- charset: 当开启批量拉取数据时,指定解析字符串数据的字符集。
|
||
- batchErrorIgnore:true:在执行 Statement 的 executeBatch 时,如果中间有一条 SQL 执行失败,继续执行下面的 SQL 了。false:不再执行失败 SQL 后的任何语句。默认值为:false。
|
||
- httpConnectTimeout: 连接超时时间,单位 ms, 默认值为 60000。
|
||
- httpSocketTimeout: socket 超时时间,单位 ms,默认值为 60000。仅在 batchfetch 设置为 false 时生效。
|
||
- messageWaitTimeout: 消息超时时间, 单位 ms, 默认值为 60000。 仅在 batchfetch 设置为 true 时生效。
|
||
- useSSL: 连接中是否使用 SSL。
|
||
- httpPoolSize: REST 并发请求大小,默认 20。
|
||
|
||
**注意**:部分配置项(比如:locale、timezone)在 REST 连接中不生效。
|
||
|
||
:::note
|
||
|
||
- 与原生连接方式不同,REST 接口是无状态的。在使用 JDBC REST 连接时,需要在 SQL 中指定表、超级表的数据库名称。例如:
|
||
|
||
```sql
|
||
INSERT INTO power.d1001 USING power.meters TAGS(2,'California.SanFrancisco') VALUES (NOW, 10.30000, 219, 0.31000);
|
||
```
|
||
|
||
- 如果在 url 中指定了 dbname,那么,JDBC REST 连接会默认使用/rest/sql/dbname 作为 restful 请求的 url,在 SQL 中不需要指定 dbname。例如:url 为 jdbc:TAOS-RS://127.0.0.1:6041/power,那么,可以执行 sql:INSERT INTO d1001 USING meters TAGS(2,'California.SanFrancisco') VALUES (NOW, 10.30000, 219, 0.31000);
|
||
|
||
:::
|
||
|
||
</TabItem>
|
||
</Tabs>
|
||
|
||
### 指定 URL 和 Properties 获取连接
|
||
|
||
除了通过指定的 URL 获取连接,还可以使用 Properties 指定建立连接时的参数。
|
||
|
||
**注意**:
|
||
|
||
- 应用中设置的 client parameter 为进程级别的,即如果要更新 client 的参数,需要重启应用。这是因为 client parameter 是全局参数,仅在应用程序的第一次设置生效。
|
||
- 以下示例代码基于 taos-jdbcdriver-3.1.0 或以上版本。
|
||
|
||
```java
|
||
public Connection getConn() throws Exception{
|
||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
||
String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/power?user=root&password=taosdata";
|
||
Properties connProps = new Properties();
|
||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||
connProps.setProperty("debugFlag", "135");
|
||
Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
|
||
return conn;
|
||
}
|
||
|
||
public Connection getRestConn() throws Exception{
|
||
Class.forName("com.taosdata.jdbc.rs.RestfulDriver");
|
||
String jdbcUrl = "jdbc:TAOS-RS://taosdemo.com:6041/power?user=root&password=taosdata";
|
||
Properties connProps = new Properties();
|
||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_BATCH_LOAD, "true");
|
||
Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
|
||
return conn;
|
||
}
|
||
```
|
||
|
||
以上示例,建立一个到 hostname 为 taosdemo.com,端口为 6030/6041,数据库名为 power 的连接。这个连接在 url 中指定了用户名(user)为 root,密码(password)为 taosdata,并在 connProps 中指定了使用的字符集、语言环境、时区、是否开启批量拉取等信息。
|
||
|
||
properties 中的配置参数如下:
|
||
|
||
- TSDBDriver.PROPERTY_KEY_USER:登录 TDengine 用户名,默认值 'root'。
|
||
- TSDBDriver.PROPERTY_KEY_PASSWORD:用户登录密码,默认值 'taosdata'。
|
||
- TSDBDriver.PROPERTY_KEY_BATCH_LOAD: true:在执行查询时批量拉取结果集;false:逐行拉取结果集。默认值为:false。
|
||
- TSDBDriver.PROPERTY_KEY_BATCH_ERROR_IGNORE:true:在执行 Statement 的 executeBatch 时,如果中间有一条 SQL 执行失败,继续执行下面的 sq 了。false:不再执行失败 SQL 后的任何语句。默认值为:false。
|
||
- TSDBDriver.PROPERTY_KEY_CONFIG_DIR:仅在使用 JDBC 原生连接时生效。客户端配置文件目录路径,Linux OS 上默认值 `/etc/taos`,Windows OS 上默认值 `C:/TDengine/cfg`。
|
||
- TSDBDriver.PROPERTY_KEY_CHARSET:客户端使用的字符集,默认值为系统字符集。
|
||
- TSDBDriver.PROPERTY_KEY_LOCALE:仅在使用 JDBC 原生连接时生效。 客户端语言环境,默认值系统当前 locale。
|
||
- TSDBDriver.PROPERTY_KEY_TIME_ZONE:仅在使用 JDBC 原生连接时生效。 客户端使用的时区,默认值为系统当前时区。因为历史的原因,我们只支持POSIX标准的部分规范,如UTC-8(代表中国上上海), GMT-8,Asia/Shanghai 这几种形式。
|
||
- TSDBDriver.HTTP_CONNECT_TIMEOUT: 连接超时时间,单位 ms, 默认值为 60000。仅在 REST 连接时生效。
|
||
- TSDBDriver.HTTP_SOCKET_TIMEOUT: socket 超时时间,单位 ms,默认值为 60000。仅在 REST 连接且 batchfetch 设置为 false 时生效。
|
||
- TSDBDriver.PROPERTY_KEY_MESSAGE_WAIT_TIMEOUT: 消息超时时间, 单位 ms, 默认值为 60000。 仅在 REST 连接且 batchfetch 设置为 true 时生效。
|
||
- TSDBDriver.PROPERTY_KEY_USE_SSL: 连接中是否使用 SSL。仅在 REST 连接时生效。
|
||
- TSDBDriver.HTTP_POOL_SIZE: REST 并发请求大小,默认 20。
|
||
- TSDBDriver.PROPERTY_KEY_ENABLE_COMPRESSION: 传输过程是否启用压缩。仅在使用 REST/Websocket 连接时生效。true: 启用,false: 不启用。默认为 false。
|
||
- TSDBDriver.PROPERTY_KEY_ENABLE_AUTO_RECONNECT: 是否启用自动重连。仅在使用 Websocket 连接时生效。true: 启用,false: 不启用。默认为 false。
|
||
> **注意**:启用自动重连仅对简单执行 SQL 语句以及 无模式写入、数据订阅有效。对于参数绑定无效。自动重连仅对连接建立时通过参数指定数据库有效,对后面的 `use db` 语句切换数据库无效。
|
||
|
||
- TSDBDriver.PROPERTY_KEY_RECONNECT_INTERVAL_MS: 自动重连重试间隔,单位毫秒,默认值 2000。仅在 PROPERTY_KEY_ENABLE_AUTO_RECONNECT 为 true 时生效。
|
||
- TSDBDriver.PROPERTY_KEY_RECONNECT_RETRY_COUNT: 自动重连重试次数,默认值 3,仅在 PROPERTY_KEY_ENABLE_AUTO_RECONNECT 为 true 时生效。
|
||
- TSDBDriver.PROPERTY_KEY_DISABLE_SSL_CERT_VALIDATION: 关闭 SSL 证书验证 。仅在使用 Websocket 连接时生效。true: 启用,false: 不启用。默认为 false。
|
||
|
||
|
||
此外对 JDBC 原生连接,通过指定 URL 和 Properties 还可以指定其他参数,比如日志级别、SQL 长度等。更多详细配置请参考[客户端配置](../../reference/config/)。
|
||
|
||
### 配置参数的优先级
|
||
|
||
通过前面三种方式获取连接,如果配置参数在 url、Properties、客户端配置文件中有重复,则参数的`优先级由高到低`分别如下:
|
||
|
||
1. JDBC URL 参数,如上所述,可以在 JDBC URL 的参数中指定。
|
||
2. Properties connProps
|
||
3. 使用原生连接时,TDengine 客户端驱动的配置文件 taos.cfg
|
||
|
||
例如:在 url 中指定了 password 为 taosdata,在 Properties 中指定了 password 为 taosdemo,那么,JDBC 会使用 url 中的 password 建立连接。
|
||
|
||
## 使用示例
|
||
|
||
### 创建数据库和表
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JdbcBasicDemo.java:create_db_and_table}}
|
||
```
|
||
|
||
> **注意**:如果不使用 `USE power` 指定数据库,则后续对表的操作都需要增加数据库名称作为前缀,如 power.meters。
|
||
|
||
### 插入数据
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JdbcBasicDemo.java:insert_data}}
|
||
```
|
||
|
||
> NOW 为系统内部函数,默认为客户端所在计算机当前时间。
|
||
> `NOW + 1s` 代表客户端当前时间往后加 1 秒,数字后面代表时间单位:a(毫秒),s(秒),m(分),h(小时),d(天),w(周),n(月),y(年)。
|
||
|
||
### 查询数据
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JdbcBasicDemo.java:query_data}}
|
||
```
|
||
|
||
> 查询和操作关系型数据库一致,使用下标获取返回字段内容时从 1 开始,建议使用字段名称获取。
|
||
|
||
### 执行带有 reqId 的 SQL
|
||
|
||
<RequestId />
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JdbcBasicDemo.java:with_reqid}}
|
||
```
|
||
|
||
### 通过参数绑定写入数据
|
||
|
||
TDengine 的 JDBC 原生连接实现大幅改进了参数绑定方式对数据写入(INSERT)场景的支持。采用这种方式写入数据时,能避免 SQL 语法解析的资源消耗,从而在很多情况下显著提升写入性能。
|
||
|
||
**注意**:
|
||
|
||
- JDBC REST 连接目前不支持参数绑定
|
||
- 以下示例代码基于 taos-jdbcdriver-3.2.1 或以上版本
|
||
- binary 类型数据需要调用 setString 方法,nchar 类型数据需要调用 setNString 方法
|
||
- 预处理语句中指定数据库与子表名称不要使用 `db.?`,应直接使用 `?`,然后在 setTableName 中指定数据库,如:`prepareStatement.setTableName("db.t1")`。
|
||
|
||
<Tabs defaultValue="native">
|
||
<TabItem value="native" label="原生连接">
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/ParameterBindingBasicDemo.java:para_bind}}
|
||
```
|
||
|
||
这是一个[更详细的参数绑定示例](https://github.com/taosdata/TDengine/blob/main/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/ParameterBindingFullDemo.java)
|
||
|
||
</TabItem>
|
||
<TabItem value="rest" label="WebSocket 连接">
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/WSParameterBindingBasicDemo.java:para_bind}}
|
||
```
|
||
|
||
|
||
这是一个[更详细的参数绑定示例](https://github.com/taosdata/TDengine/blob/main/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/WSParameterBindingFullDemo.java)
|
||
|
||
</TabItem>
|
||
</Tabs>
|
||
|
||
用于设定 VALUES 数据列的取值的方法总共有:
|
||
|
||
```java
|
||
public void setInt(int columnIndex, ArrayList<Integer> list) throws SQLException
|
||
public void setFloat(int columnIndex, ArrayList<Float> list) throws SQLException
|
||
public void setTimestamp(int columnIndex, ArrayList<Long> list) throws SQLException
|
||
public void setLong(int columnIndex, ArrayList<Long> list) throws SQLException
|
||
public void setDouble(int columnIndex, ArrayList<Double> list) throws SQLException
|
||
public void setBoolean(int columnIndex, ArrayList<Boolean> list) throws SQLException
|
||
public void setByte(int columnIndex, ArrayList<Byte> list) throws SQLException
|
||
public void setShort(int columnIndex, ArrayList<Short> list) throws SQLException
|
||
public void setString(int columnIndex, ArrayList<String> list, int size) throws SQLException
|
||
public void setNString(int columnIndex, ArrayList<String> list, int size) throws SQLException
|
||
public void setVarbinary(int columnIndex, ArrayList<byte[]> list, int size) throws SQLException
|
||
public void setGeometry(int columnIndex, ArrayList<byte[]> list, int size) throws SQLException
|
||
```
|
||
**注**:字符串和数组类型都要求用户在 size 参数里声明表定义中对应列的列宽。
|
||
|
||
用于设定 TAGS 取值的方法总共有:
|
||
|
||
```java
|
||
public void setTagNull(int index, int type)
|
||
public void setTagBoolean(int index, boolean value)
|
||
public void setTagInt(int index, int value)
|
||
public void setTagByte(int index, byte value)
|
||
public void setTagShort(int index, short value)
|
||
public void setTagLong(int index, long value)
|
||
public void setTagTimestamp(int index, long value)
|
||
public void setTagFloat(int index, float value)
|
||
public void setTagDouble(int index, double value)
|
||
public void setTagString(int index, String value)
|
||
public void setTagNString(int index, String value)
|
||
public void setTagJson(int index, String value)
|
||
public void setTagVarbinary(int index, byte[] value)
|
||
public void setTagGeometry(int index, byte[] value)
|
||
```
|
||
|
||
### 无模式写入
|
||
|
||
TDengine 支持无模式写入功能。无模式写入兼容 InfluxDB 的 行协议(Line Protocol)、OpenTSDB 的 telnet 行协议和 OpenTSDB 的 JSON 格式协议。详情请参见[无模式写入](../../reference/schemaless/)。
|
||
|
||
<Tabs defaultValue="native">
|
||
<TabItem value="native" label="原生连接">
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/SchemalessJniTest.java:schemaless}}
|
||
```
|
||
|
||
</TabItem>
|
||
<TabItem value="ws" label="WebSocket 连接">
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/SchemalessWsTest.java:schemaless}}
|
||
```
|
||
|
||
</TabItem>
|
||
</Tabs>
|
||
|
||
### 执行带有 reqId 的无模式写入
|
||
|
||
此 reqId 可用于请求链路追踪。
|
||
|
||
```java
|
||
writer.write(lineDemo, SchemalessProtocolType.LINE, SchemalessTimestampType.NANO_SECONDS, 1L);
|
||
```
|
||
|
||
### 数据订阅
|
||
|
||
TDengine Java 连接器支持订阅功能,应用 API 如下:
|
||
|
||
#### 创建 Topic
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/ConsumerLoopImp.java:create_topic}}
|
||
```
|
||
|
||
如上面的例子将使用 SQL 语句 `SELECT ts, current, voltage, phase, groupid, location FROM meters` 创建一个名为 `topic_meters` 的主题。
|
||
> **注意**:订阅主题的查询语句只能是 `SELECT` 语句,只应查询原始数据,只能按时间正序查询数据。
|
||
|
||
#### 创建 Consumer
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/AbsConsumerLoop.java:create_consumer}}
|
||
```
|
||
|
||
- td.connect.type: 连接方式。jni:表示使用动态库连接的方式,ws/WebSocket:表示使用 WebSocket 进行数据通信。默认为 jni 方式。
|
||
- bootstrap.servers: TDengine 服务端所在的`ip:port`,如果使用 WebSocket 连接,则为 taosAdapter 所在的`ip:port`。
|
||
- enable.auto.commit: 是否允许自动提交。
|
||
- group.id: consumer: 所在的 group。
|
||
- value.deserializer: 结果集反序列化方法,可以继承 `com.taosdata.jdbc.tmq.ReferenceDeserializer`,并指定结果集 bean,实现反序列化。也可以继承 `com.taosdata.jdbc.tmq.Deserializer`,根据 SQL 的 resultSet 自定义反序列化方式。
|
||
- httpConnectTimeout: 创建连接超时参数,单位 ms,默认为 5000 ms。仅在 WebSocket 连接下有效。
|
||
- messageWaitTimeout: 数据传输超时参数,单位 ms,默认为 10000 ms。仅在 WebSocket 连接下有效。
|
||
- httpPoolSize: 同一个连接下最大并行请求数。仅在 WebSocket 连接下有效。
|
||
- TSDBDriver.PROPERTY_KEY_ENABLE_COMPRESSION: 传输过程是否启用压缩。仅在使用 Websocket 连接时生效。true: 启用,false: 不启用。默认为 false。
|
||
- TSDBDriver.PROPERTY_KEY_ENABLE_AUTO_RECONNECT: 是否启用自动重连。仅在使用 Websocket 连接时生效。true: 启用,false: 不启用。默认为 false。
|
||
- TSDBDriver.PROPERTY_KEY_RECONNECT_INTERVAL_MS: 自动重连重试间隔,单位毫秒,默认值 2000。仅在 PROPERTY_KEY_ENABLE_AUTO_RECONNECT 为 true 时生效。
|
||
- TSDBDriver.PROPERTY_KEY_RECONNECT_RETRY_COUNT: 自动重连重试次数,默认值 3,仅在 PROPERTY_KEY_ENABLE_AUTO_RECONNECT 为 true 时生效。
|
||
|
||
其他参数请参考:[Consumer 参数列表](../../develop/tmq/#数据订阅相关参数), 注意TDengine服务端自 3.2.0.0 版本开始消息订阅中的 auto.offset.reset 默认值发生变化。
|
||
|
||
#### 订阅消费数据
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/AbsConsumerLoop.java:poll_data}}
|
||
```
|
||
|
||
`subscribe` 方法的参数含义如为:订阅的主题列表(即名称),支持同时订阅多个主题。
|
||
`poll` 每次调用获取一个消息,一个消息中可能包含多个记录。
|
||
|
||
#### 指定订阅 Offset
|
||
|
||
```java
|
||
// 获取订阅的 topicPartition
|
||
Set<TopicPartition> assignment() throws SQLException;
|
||
// 获取 offset
|
||
long position(TopicPartition partition) throws SQLException;
|
||
Map<TopicPartition, Long> position(String topic) throws SQLException;
|
||
Map<TopicPartition, Long> beginningOffsets(String topic) throws SQLException;
|
||
Map<TopicPartition, Long> endOffsets(String topic) throws SQLException;
|
||
Map<TopicPartition, OffsetAndMetadata> committed(Set<TopicPartition> partitions) throws SQLException;
|
||
|
||
// 指定下一次 poll 中使用的 offset
|
||
void seek(TopicPartition partition, long offset) throws SQLException;
|
||
void seekToBeginning(Collection<TopicPartition> partitions) throws SQLException;
|
||
void seekToEnd(Collection<TopicPartition> partitions) throws SQLException;
|
||
```
|
||
|
||
示例代码:
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/ConsumerOffsetSeek.java:consumer_seek}}
|
||
```
|
||
|
||
#### 提交 Offset
|
||
|
||
当`enable.auto.commit`为 false 时,可以手动提交 offset。
|
||
|
||
```java
|
||
void commitSync() throws SQLException;
|
||
void commitSync(Map<TopicPartition, OffsetAndMetadata> offsets) throws SQLException;
|
||
// 异步提交仅在 native 连接下有效
|
||
void commitAsync(OffsetCommitCallback<V> callback) throws SQLException;
|
||
void commitAsync(Map<TopicPartition, OffsetAndMetadata> offsets, OffsetCommitCallback<V> callback) throws SQLException;
|
||
```
|
||
|
||
#### 关闭订阅
|
||
|
||
```java
|
||
// 取消订阅
|
||
consumer.unsubscribe();
|
||
// 关闭消费
|
||
consumer.close()
|
||
```
|
||
|
||
详情请参考:[数据订阅](../../develop/tmq)
|
||
|
||
#### 完整示例
|
||
|
||
<Tabs defaultValue="native">
|
||
<TabItem value="native" label="原生连接">
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/AbsConsumerLoopFull.java:consumer_demo}}
|
||
```
|
||
|
||
</TabItem>
|
||
<TabItem value="ws" label="WebSocket 连接">
|
||
|
||
除了原生的连接方式,Java 连接器还支持通过 WebSocket 订阅数据。
|
||
|
||
```java
|
||
{{#include examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/AbsWsConsumerLoop.java:consumer_demo}}
|
||
```
|
||
|
||
</TabItem>
|
||
</Tabs>
|
||
|
||
> **注意**:这里的 value.deserializer 配置参数值应该根据测试环境的包路径做相应的调整。
|
||
|
||
### 与连接池使用
|
||
|
||
#### HikariCP
|
||
|
||
使用示例如下:
|
||
|
||
```java
|
||
{{#include examples/JDBC/connectionPools/src/main/java/com/taosdata/example/HikariDemo.java:connection_pool}}
|
||
```
|
||
|
||
> 通过 HikariDataSource.getConnection() 获取连接后,使用完成后需要调用 close() 方法,实际上它并不会关闭连接,只是放回连接池中。
|
||
> 更多 HikariCP 使用问题请查看[官方说明](https://github.com/brettwooldridge/HikariCP)。
|
||
|
||
#### Druid
|
||
|
||
使用示例如下:
|
||
|
||
```java
|
||
{{#include examples/JDBC/connectionPools/src/main/java/com/taosdata/example/DruidDemo.java:connection_pool}}
|
||
```
|
||
|
||
> 更多 druid 使用问题请查看[官方说明](https://github.com/alibaba/druid)。
|
||
|
||
### 更多示例程序
|
||
|
||
示例程序源码位于 `TDengine/examples/JDBC` 下:
|
||
|
||
- JDBCDemo:JDBC 示例源程序。
|
||
- connectionPools:HikariCP, Druid, dbcp, c3p0 等连接池中使用 taos-jdbcdriver。
|
||
- SpringJdbcTemplate:Spring JdbcTemplate 中使用 taos-jdbcdriver。
|
||
- mybatisplus-demo:Springboot + Mybatis 中使用 taos-jdbcdriver。
|
||
- springbootdemo: Springboot 中使用 taos-jdbcdriver。
|
||
- consumer-demo:Consumer 消费 TDengine 数据示例,可通过参数控制消费速度。
|
||
|
||
请参考:[JDBC example](https://github.com/taosdata/TDengine/tree/3.0/examples/JDBC)
|
||
|
||
## 常见问题
|
||
|
||
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+ 环境使用。
|
||
|
||
**解决方法**: 更换 taos-jdbcdriver 3.0.2+ 版本。
|
||
|
||
其它问题请参考 [FAQ](../../train-faq/faq)
|
||
|
||
## API 参考
|
||
|
||
[taos-jdbcdriver doc](https://docs.taosdata.com/api/taos-jdbcdriver)
|