> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-fix-nav-issues.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> Java ClickHouse 客户端

# Java 客户端

export const WideTableWrapper = ({children}) => {
  const containerStyle = {
    overflow: "auto",
    maxWidth: "100%"
  };
  return <div style={containerStyle}>{children}</div>;
};

<a id="migration_from_v1_config" />

<View title="v0.8+">
  用于通过协议与数据库服务器通信的 Java 客户端库。当前实现仅支持 [HTTP interface](/zh/concepts/features/interfaces/http)。
  该库提供了自有 API，用于向服务器发送请求，同时还提供了处理不同二进制数据格式 (RowBinary\* & Native\*) 的工具。

  ## 设置

  * Maven Central (项目页面) ：[https://mvnrepository.com/artifact/com.clickhouse/client-v2](https://mvnrepository.com/artifact/com.clickhouse/client-v2)
  * 夜间构建 (仓库链接) ：[https://central.sonatype.com/repository/maven-snapshots/](https://central.sonatype.com/repository/maven-snapshots/)
  * 旧版 Nightly 构建制品库 (仓库链接) ：[https://s01.oss.sonatype.org/content/repositories/snapshots/](https://s01.oss.sonatype.org/content/repositories/snapshots/)

  <br />

  <Tabs>
    <Tab title="Maven">
      ```xml theme={null}
      <dependency>
          <groupId>com.clickhouse</groupId>
          <artifactId>client-v2</artifactId>
          <version>0.9.8</version>
      </dependency>
      ```
    </Tab>

    <Tab title="Gradle (Kotlin)">
      ```kotlin theme={null}
      // https://mvnrepository.com/artifact/com.clickhouse/client-v2
      implementation("com.clickhouse:client-v2:0.9.8")
      ```
    </Tab>

    <Tab title="Gradle">
      ```groovy theme={null}
      // https://mvnrepository.com/artifact/com.clickhouse/client-v2
      implementation 'com.clickhouse:client-v2:0.9.8'
      ```
    </Tab>
  </Tabs>

  <br />

  ## 初始化

  Client 对象通过 `com.clickhouse.client.api.Client.Builder#build()` 初始化。每个客户端拥有独立的上下文，客户端之间不共享任何对象。
  Builder 提供了多种配置方法，方便快速完成设置。

  示例：

  ```java showLineNumbers theme={null}
  Client client = new Client.Builder()
                  .addEndpoint("https://clickhouse-cloud-instance:8443/")
                  .setUsername(user)
                  .setPassword(password)
                  .build();
  ```

  `Client` 实现了 `AutoCloseable` 接口，不再需要时应将其关闭。

  ### 身份验证

  身份验证在初始化阶段按客户端进行配置。支持三种身份验证方法：密码、访问令牌以及 SSL 客户端证书。

  通过密码进行身份验证需要调用 `setUsername(String)` 和 `setPassword(String)` 来设置用户名和密码：

  ```java showLineNumbers theme={null}
  Client client = new Client.Builder()
          .addEndpoint("https://clickhouse-cloud-instance:8443/")
          .setUsername(user)
          .setPassword(password)
          .build();
  ```

  使用访问令牌进行身份验证需要调用 `setAccessToken(String)` 来设置访问令牌：

  ```java showLineNumbers theme={null}
  Client client = new Client.Builder()
          .addEndpoint("https://clickhouse-cloud-instance:8443/")
          .setAccessToken(userAccessToken)
          .build();
  ```

  通过 SSL 客户端证书进行身份验证，需要分别调用 `setUsername(String)`、`useSSLAuthentication(boolean)`、`setClientCertificate(String)` 和 `setClientKey(String)` 来设置用户名、启用 SSL 身份验证、设置客户端证书和客户端密钥：

  ```java showLineNumbers theme={null}
  Client client = new Client.Builder()
          .useSSLAuthentication(true)
          .setUsername("some_user")
          .setClientCertificate("some_user.crt")
          .setClientKey("some_user.key")
  ```

  <Note>
    在生产环境中，SSL 身份验证往往很难排查，因为 SSL 库返回的很多错误信息都不够充分。例如，如果客户端证书与密钥不匹配，server 会立即终止 connection (对于 HTTP，这会发生在 connection 建立阶段，此时还不会发送任何 HTTP request，因此也不会返回任何响应) 。

    请使用 [openssl](https://docs.openssl.org/master/man1/openssl/) 等工具验证证书和密钥：

    * 检查密钥完整性：`openssl rsa -in [key-file.key] -check -noout`
    * 检查客户端证书是否包含与用户匹配的 CN：
      * 从用户证书中获取 CN：`openssl x509 -noout -subject -in [user.cert]`
      * 验证 database 中是否设置了相同的值：`select name, auth_type, auth_params from system.users where auth_type = 'ssl_certificate'` (该查询会输出 `auth_params`，类似 ` {"common_names":["some_user"]}`)
  </Note>

  ## 配置

  所有设置均通过实例方法 (即配置方法) 定义，使每个值的作用域和上下文一目了然。
  主要配置参数在单一作用域 (客户端或操作) 内定义，彼此之间不会相互覆盖。

  配置在客户端创建时定义。请参阅 `com.clickhouse.client.api.Client.Builder`。

  ## 客户端配置

  <Tabs>
    <Tab title="连接与端点">
      | 方法                                                                      | 参数                                                               | 描述                                                 | 默认值       | 键                           |
      | ----------------------------------------------------------------------- | ---------------------------------------------------------------- | -------------------------------------------------- | --------- | --------------------------- |
      | `addEndpoint(String endpoint)`                                          | `endpoint` - URL 格式的服务器地址                                        | 将服务器端点添加到可用服务器列表。目前仅支持一个端点。                        | `none`    | `none`                      |
      | `addEndpoint(Protocol protocol, String host, int port, boolean secure)` | `protocol` - 连接协议<br />`host` - IP 或主机名<br />`secure` - 使用 HTTPS | 将服务器端点添加到可用服务器列表。目前仅支持一个端点。                        | `none`    | `none`                      |
      | `enableConnectionPool(boolean enable)`                                  | `enable` - 用于启用/禁用的标志                                            | 设置是否启用连接池。                                         | `true`    | `connection_pool_enabled`   |
      | `setMaxConnections(int maxConnections)`                                 | `maxConnections` - 连接数                                           | 设置客户端可为每个服务器端点打开的连接数。                              | `10`      | `max_open_connections`      |
      | `setConnectionTTL(long timeout, ChronoUnit unit)`                       | `timeout` - 超时值<br />`unit` - 时间单位                               | 设置连接的生存时间 (TTL)，超过该时间后，连接将被视为非活动状态。                | `-1`      | `connection_ttl`            |
      | `setKeepAliveTimeout(long timeout, ChronoUnit unit)`                    | `timeout` - 超时值<br />`unit` - 时间单位                               | 设置 HTTP 连接的 Keep-Alive 超时时间。设为 `0` 可禁用 Keep-Alive。 | -         | `http_keep_alive_timeout`   |
      | `setConnectionReuseStrategy(ConnectionReuseStrategy strategy)`          | `strategy` - `LIFO` 或 `FIFO`                                     | 选择连接池使用的策略。                                        | `FIFO`    | `connection_reuse_strategy` |
      | `setDefaultDatabase(String database)`                                   | `database` - 数据库名称                                               | 设置默认数据库。                                           | `default` | `database`                  |
    </Tab>

    <Tab title="身份验证">
      | 方法                                                   | 参数                                      | 描述                                                 | 默认值       | 键                     |
      | ---------------------------------------------------- | --------------------------------------- | -------------------------------------------------- | --------- | --------------------- |
      | `setUsername(String username)`                       | `username` - 用于身份验证的用户名                 | 为后续配置所选的身份验证方法设置用户名                                | `default` | `user`                |
      | `setPassword(String password)`                       | `password` - 机密值                        | 设置用于密码身份验证的机密值，并将密码身份验证设为所用的身份验证方法                 | -         | `password`            |
      | `setAccessToken(String accessToken)`                 | `accessToken` - 访问令牌字符串                 | 设置用于身份验证的访问令牌，并选择相应的身份验证方法                         | -         | `access_token`        |
      | `useSSLAuthentication(boolean useSSLAuthentication)` | `useSSLAuthentication` - 启用 SSL 身份验证的标志 | 将 SSL 客户端证书设为身份验证方法。                               | -         | `ssl_authentication`  |
      | `useHTTPBasicAuth(boolean useBasicAuth)`             | `useBasicAuth` - 启用/禁用标志                | 设置是否使用 HTTP 基本身份验证进行用户名和密码身份验证。可解决密码中包含特殊字符时出现的问题。 | `true`    | `http_use_basic_auth` |
      | `useBearerTokenAuth(String bearerToken)`             | `bearerToken` - 已编码的 Bearer 令牌          | 指定是否使用 Bearer 身份验证以及使用哪个令牌。该令牌将按原样发送。              | -         | `bearer_token`        |
    </Tab>

    <Tab title="超时与重试">
      | 方法                                                           | 参数                                     | 描述                                   | 默认值                                                          | 键                            |
      | ------------------------------------------------------------ | -------------------------------------- | ------------------------------------ | ------------------------------------------------------------ | ---------------------------- |
      | `setConnectTimeout(long timeout, ChronoUnit unit)`           | `timeout` - 超时值<br />`unit` - 时间单位     | 设置任何传出连接的建立超时时间。                     | -                                                            | `connection_timeout`         |
      | `setConnectionRequestTimeout(long timeout, ChronoUnit unit)` | `timeout` - 超时值<br />`unit` - 时间单位     | 设置连接请求超时时间。仅在从连接池获取连接时生效。            | `10000`                                                      | `connection_request_timeout` |
      | `setSocketTimeout(long timeout, ChronoUnit unit)`            | `timeout` - 超时值<br />`unit` - 时间单位     | 设置会影响读写操作的套接字超时时间                    | `0`                                                          | `socket_timeout`             |
      | `setExecutionTimeout(long timeout, ChronoUnit timeUnit)`     | `timeout` - 超时值<br />`timeUnit` - 时间单位 | 设置查询的最大执行超时时间                        | `0`                                                          | `max_execution_time`         |
      | `retryOnFailures(ClientFaultCause ...causes)`                | `causes` - `ClientFaultCause` 的枚举常量    | 设置可恢复或可重试的故障类型。                      | `NoHttpResponse` `ConnectTimeout` `ConnectionRequestTimeout` | `client_retry_on_failures`   |
      | `setMaxRetries(int maxRetries)`                              | `maxRetries` - 重试次数                    | 设置由 `retryOnFailures` 定义的失败类型的最大重试次数 | `3`                                                          | `retry`                      |
    </Tab>

    <Tab title="套接字选项">
      | 方法                                   | 参数                      | 描述                                                                 | 默认值    | 键                    |
      | ------------------------------------ | ----------------------- | ------------------------------------------------------------------ | ------ | -------------------- |
      | `setSocketRcvbuf(long size)`         | `size` - 以字节为单位的大小      | 设置 TCP 套接字接收缓冲区。该缓冲区位于 JVM 内存之外。                                   | `8196` | `socket_rcvbuf`      |
      | `setSocketSndbuf(long size)`         | `size` - 以字节为单位的大小      | 设置 TCP 套接字发送缓冲区。该缓冲区位于 JVM 内存之外。                                   | `8196` | `socket_sndbuf`      |
      | `setSocketKeepAlive(boolean value)`  | `value` - 启用/禁用标志       | 为每个 TCP 套接字设置 `SO_KEEPALIVE` 选项。TCP Keep-Alive 会启用一种用于检查连接存活状态的机制。 | -      | `socket_keepalive`   |
      | `setSocketTcpNodelay(boolean value)` | `value` - 启用/禁用标志       | 为每个 TCP 套接字设置 `SO_NODELAY` 选项。该 TCP 选项会使套接字尽可能立即发送数据。              | -      | `socket_tcp_nodelay` |
      | `setSocketLinger(int secondsToWait)` | `secondsToWait` - 等待的秒数 | 为客户端创建的每个 TCP 套接字设置延迟关闭时间。                                         | -      | `socket_linger`      |
    </Tab>

    <Tab title="压缩">
      | 方法                                        | 参数                  | 描述                                 | 默认值     | 键                                          |
      | ----------------------------------------- | ------------------- | ---------------------------------- | ------- | ------------------------------------------ |
      | `compressServerResponse(boolean enabled)` | `enabled` - 启用/禁用标志 | 设置服务端是否压缩响应。                       | `true`  | `compress`                                 |
      | `compressClientRequest(boolean enabled)`  | `enabled` - 启用/禁用标志 | 设置客户端是否压缩请求。                       | `false` | `decompress`                               |
      | `useHttpCompression(boolean enabled)`     | `enabled` - 启用/禁用标志 | 如果已启用相应选项，设置客户端/服务端通信是否使用 HTTP 压缩  | -       | -                                          |
      | `appCompressedData(boolean enabled)`      | `enabled` - 启用/禁用标志 | 告知客户端压缩将由应用程序处理。                   | `false` | `app_compressed_data`                      |
      | `setLZ4UncompressedBufferSize(int size)`  | `size` - 大小 (字节)    | 设置用于接收数据 stream 中未压缩部分的 buffer 大小。 | `65536` | `compression.lz4.uncompressed_buffer_size` |
      | `disableNativeCompression`                | `disable` - 禁用标志    | 禁用原生压缩。若设为 `true`，则会禁用原生压缩。        | `false` | `disable_native_compression`               |
    </Tab>

    <Tab title="SSL/安全">
      | 方法                                          | 参数                  | 描述                                        | 默认值 | Key                  |
      | ------------------------------------------- | ------------------- | ----------------------------------------- | --- | -------------------- |
      | `setSSLTrustStore(String path)`             | `path` - 本地系统上的文件路径 | 设置客户端是否使用 SSL 信任库来验证服务器主机。                | -   | `trust_store`        |
      | `setSSLTrustStorePassword(String password)` | `password` - 敏感值    | 设置用于解锁由 `setSSLTrustStore` 指定的 SSL 信任库的密码 | -   | `key_store_password` |
      | `setSSLTrustStoreType(String type)`         | `type` - 信任库类型名称    | 设置由 `setSSLTrustStore` 指定的信任库类型。          | -   | `key_store_type`     |
      | `setRootCertificate(String path)`           | `path` - 本地系统上的文件路径 | 设置客户端是否使用指定的根 (CA) 证书来验证服务器主机。            | -   | `sslrootcert`        |
      | `setClientCertificate(String path)`         | `path` - 本地系统上的文件路径 | 设置客户端证书路径，该证书在建立 SSL 连接时使用，并用于 SSL 身份验证。  | -   | `sslcert`            |
      | `setClientKey(String path)`                 | `path` - 本地系统上的文件路径 | 设置用于加密与服务器之间 SSL 通信的客户端私钥。                | -   | `ssl_key`            |
      | `sslSocketSNI(String sni)`                  | `sni` - 服务器名称字符串    | 设置在 SSL/TLS 连接中用于 SNI (服务器名称指示) 的服务器名称。   | -   | `ssl_socket_sni`     |
    </Tab>

    <Tab title="代理">
      | 方法                                                | 参数                                                       | 描述               | 默认值 | 键                                        |
      | ------------------------------------------------- | -------------------------------------------------------- | ---------------- | --- | ---------------------------------------- |
      | `addProxy(ProxyType type, String host, int port)` | `type` - 代理类型<br />`host` - 代理主机名或 IP<br />`port` - 代理端口 | 设置与服务器通信时使用的代理。  | -   | `proxy_type`, `proxy_host`, `proxy_port` |
      | `setProxyCredentials(String user, String pass)`   | `user` - 代理用户名<br />`pass` - 密码                          | 设置用于代理身份验证的用户凭据。 | -   | `proxy_user`, `proxy_password`           |
    </Tab>

    <Tab title="HTTP 和请求头">
      | 方法                                          | 参数                                       | 描述                                                                                                                     | 默认值     | 键                                        |
      | ------------------------------------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------- | ---------------------------------------- |
      | `setHttpCookiesEnabled(boolean enabled)`    | `enabled` - 启用/禁用标志                      | 设置是否记住 HTTP cookies 并将其再次发送给服务器。                                                                                       | -       | -                                        |
      | `httpHeader(String key, String value)`      | `key` - HTTP 请求头键<br />`value` - 字符串值    | 为单个 HTTP 请求头设置值。之前的值会被覆盖。                                                                                              | `none`  | `none`                                   |
      | `httpHeader(String key, Collection values)` | `key` - HTTP 请求头键<br />`values` - 字符串值列表 | 为单个 HTTP 请求头设置多个值。之前的值会被覆盖。                                                                                            | `none`  | `none`                                   |
      | `httpHeaders(Map headers)`                  | `headers` - 包含 HTTP 请求头的映射               | 一次设置多个 HTTP 请求头的值。                                                                                                     | `none`  | `none`                                   |
      | `useHttpFormDataForQuery(boolean enable)`   | `enable` - 启用/禁用标志                       | 设置是否将查询参数作为请求体中的 HTTP form data 发送，而不是通过 URL 发送。仅适用于服务端压缩。如果启用了客户端级别的压缩，则对于带参数的查询请求会禁用该压缩，因为每个参数都会以 multipart 内容的形式发送。 | `false` | `client.http.use_form_request_for_query` |
    </Tab>

    <Tab title="服务器设置">
      | 方法                                              | 参数                                | 描述                                                                                                                                            | 默认值       | 键                        |
      | ----------------------------------------------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------------------------ |
      | `serverSetting(String name, String value)`      | `name` - 设置名称<br />`value` - 设置值  | 设置每个查询发送到服务器时携带的 settings。单个操作的 settings 可以覆盖此设置。[设置列表](/zh/concepts/features/configuration/settings/settings-query-level)                    | `none`    | `none`                   |
      | `serverSetting(String name, Collection values)` | `name` - 设置名称<br />`values` - 设置值 | 设置查询发送到服务器时携带的多值 settings，例如 [角色](/zh/concepts/features/interfaces/http#setting-role-with-query-parameters)                                   | `none`    | `none`                   |
      | `setOption("custom_settings_prefix", value)`    | `value` - 前缀字符串                   | 设置传递给服务器的自定义 settings 前缀。应与服务器配置保持一致。参见 [ClickHouse Docs](/zh/concepts/features/configuration/settings/settings-query-level#custom_settings)。 | `custom_` | `custom_settings_prefix` |
    </Tab>

    <Tab title="时区">
      | 方法                                             | 参数                            | 说明                                                | 默认值    | 键                      |
      | ---------------------------------------------- | ----------------------------- | ------------------------------------------------- | ------ | ---------------------- |
      | `useServerTimeZone(boolean useServerTimeZone)` | `useServerTimeZone` - 启用/禁用标志 | 设置客户端在解码 DateTime 和 Date 列值时是否使用服务器时区。            | `true` | `use_server_time_zone` |
      | `useTimeZone(String timeZone)`                 | `timeZone` - Java 有效的时区 ID    | 设置客户端在解码 DateTime 和 Date 列值时是否使用指定时区。此设置会覆盖服务器时区。 | -      | `use_time_zone`        |
      | `setServerTimeZone(String timeZone)`           | `timeZone` - Java 有效的时区 ID    | 设置服务端时区。默认使用 UTC 时区。                              | `UTC`  | `server_time_zone`     |
    </Tab>

    <Tab title="高级">
      | 方法                                                                        | 参数                                                      | 描述                                                                                 | 默认值      | 键                            |
      | ------------------------------------------------------------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------- | -------- | ---------------------------- |
      | `setOption(String key, String value)`                                     | `key` - 配置选项键<br />`value` - 选项值                        | 设置客户端选项的原始值。在从属性文件读取配置时非常有用。                                                       | -        | -                            |
      | `useAsyncRequests(boolean async)`                                         | `async` - 启用/禁用标志                                       | 设置客户端是否应在单独的线程中执行请求。默认禁用，因为应用程序更清楚如何组织多线程任务。                                       | `false`  | `async`                      |
      | `setSharedOperationExecutor(ExecutorService executorService)`             | `executorService` - 执行器服务实例                             | 为操作任务设置执行器服务。                                                                      | `none`   | `none`                       |
      | `setQueryIdGenerator(Supplier<String> supplier)`                          | `supplier` - 用于生成查询 ID 的 `Supplier<String>`             | 设置自定义查询 ID 生成器，在操作设置 (`InsertSettings`, `QuerySettings`) 中未指定查询 ID 时使用。            | -        | -                            |
      | `setClientNetworkBufferSize(int size)`                                    | `size` - 大小 (以字节为单位)                                    | 设置应用程序内存空间中 buffer 的大小，该 buffer 用于在套接字与应用程序之间复制数据。                                 | `300000` | `client_network_buffer_size` |
      | `allowBinaryReaderToReuseBuffers(boolean reuse)`                          | `reuse` - 启用/禁用标志                                       | 如果启用，reader 将使用预分配的 buffer 进行数值转码，从而降低数值数据的 GC 压力。                                 | -        | -                            |
      | `columnToMethodMatchingStrategy(ColumnToMethodMatchingStrategy strategy)` | `strategy` - 匹配策略实现                                     | 设置自定义策略，用于在注册 DTO 时匹配 DTO 类字段与 DB 列。                                               | `none`   | `none`                       |
      | `setClientName(String clientName)`                                        | `clientName` - 应用程序名称字符串                                | 设置调用应用程序的附加信息。该信息将作为 `User-Agent` 请求头传递。                                           | -        | `client_name`                |
      | `registerClientMetrics(Object registry, String name)`                     | `registry` - Micrometer registry 实例<br />`name` - 指标组名称 | 使用 Micrometer ([https://micrometer.io/](https://micrometer.io/)) registry 实例注册传感器。 | -        | -                            |
      | `setServerVersion(String version)`                                        | `version` - 服务器版本字符串                                    | 设置服务器版本以避免进行版本检测。                                                                  | -        | `server_version`             |
      | `typeHintMapping(Map typeHintMapping)`                                    | `typeHintMapping` - type hint 映射                        | 为 ClickHouse 类型设置 type hint 映射。例如，可使多维数组以 Java 容器的形式呈现。                            | -        | `type_hint_mapping`          |
    </Tab>
  </Tabs>

  <br />

  ### 客户端识别

  查询日志中有两个字段用于标识发起请求的应用程序：`client_name` 和 `http_user_agent`。Native TCP 协议使用 `client_name` 标识应用程序，HTTP 协议使用 `http_user_agent` 标识应用程序。Client builder 提供了 `setClientName` 方法，可为两种协议正确设置相应的值。
  字段 `http_user_agent` 遵循 `User-Agent` 请求头的通用格式：`application-name[/version] [(operating-system; architecture; ...)]`。
  这组值会在每个 layer 中重复出现：应用程序层、客户端库层、HTTP 客户端库层。由 `setClientName` 方法设置的内容在列表中排在最前面。

  例如：

  ```java showLineNumbers theme={null}
  client.setClientName("my-app-01/1.0");
  ```

  将产生以下 `http_user_agent` 值：

  ```
  my-app-01/1.0 clickhouse-java-v2/0.9.6-SNAPSHOT (Linux; jvm:17.0.17) Apache-HttpClient/5.4.4
  ```

  应用程序可以设置自定义 HTTP 请求头 `User-Agent` 来标识自身，但 `clickhouse-java-v2/0.9.6-SNAPSHOT` 部分会自动追加到该请求头的末尾。

  ### 操作标识

  查询日志还有另外两个字段 `query_id` 和 `log_comment`，可用于标识操作并向查询日志添加额外信息。

  `query_id` 是操作的唯一标识符。应用程序可通过调用 `QuerySettings` 类的 `setQueryId` 方法来设置该值。

  ```java showLineNumbers theme={null}
  QuerySettings querySettings = new QuerySettings();
  querySettings.setQueryId("some-query-id");
  ```

  `log_comment` 是一个可以添加到查询日志中的注释。应用程序可以通过调用 `QuerySettings` 类的 `logComment` 方法来设置此注释。

  ```java showLineNumbers theme={null}
  QuerySettings querySettings = new QuerySettings();
  querySettings.logComment("some-comment");
  ```

  ### 服务器设置

  服务器端配置可以在创建客户端时统一设置 (参见 `Builder` 的 `serverSetting` 方法) ，也可以在操作级别单独设置 (参见操作配置类的 `serverSetting`) 。

  ```java showLineNumbers theme={null}
  try (Client client = new Client.Builder().addEndpoint(Protocol.HTTP, "localhost", mockServer.port(), false)
          .setUsername("default")
          .setPassword(ClickHouseServerForTest.getPassword())
          .compressClientRequest(true)

          // 客户端级别
          .serverSetting("max_threads", "10")
          .serverSetting("async_insert", "1")
          .serverSetting("roles", Arrays.asList("role1", "role2"))

          .build()) {

  	// 操作级别
  	QuerySettings querySettings = new QuerySettings();
  	querySettings.serverSetting("session_timezone", "Europe/Zurich");

  	...
  }
  ```

  ⚠️ 当通过 `setOption` 方法 (`Client.Builder` 或操作设置类) 设置选项时，server settings 名称应加上 `clickhouse_setting_` 前缀。此时 `com.clickhouse.client.api.ClientConfigProperties#serverSetting()` 会很有帮助。

  ### 自定义 HTTP 请求头

  可以为所有操作 (客户端级别) 或单个操作 (操作级别) 设置自定义 HTTP 请求头。

  ```java showLineNumbers theme={null}
  QuerySettings settings = new QuerySettings()
      .httpHeader(HttpHeaders.REFERER, clientReferer)
      .setQueryId(qId);
  ```

  通过 `setOption` 方法 (`Client.Builder` 或操作设置类) 设置选项时，自定义请求头名称应以 `http_header_` 为前缀。在这种情况下，`com.clickhouse.client.api.ClientConfigProperties#httpHeader()` 方法会很有帮助。

  ## 常用定义

  ### ClickHouseFormat

  [支持格式](/zh/reference/formats)的枚举类型，包含 ClickHouse 支持的所有格式。

  * `raw` - 用户应对原始数据进行转码
  * `full` - 客户端可以自行转码数据，并接收原始数据流
  * `-` - ClickHouse 不支持此格式的该操作

  此客户端版本支持：

  | 格式                                                                                                                  |  输入  |  输出  |
  | ------------------------------------------------------------------------------------------------------------------- | :--: | :--: |
  | [TabSeparated](/zh/reference/formats/TabSeparated/TabSeparated)                                                     |  raw |  raw |
  | [TabSeparatedRaw](/zh/reference/formats/TabSeparated/TabSeparatedRaw)                                               |  raw |  raw |
  | [TabSeparatedWithNames](/zh/reference/formats/TabSeparated/TabSeparatedWithNames)                                   |  raw |  raw |
  | [TabSeparatedWithNamesAndTypes](/zh/reference/formats/TabSeparated/TabSeparatedWithNamesAndTypes)                   |  raw |  raw |
  | [TabSeparatedRawWithNames](/zh/reference/formats/TabSeparated/TabSeparatedRawWithNames)                             |  raw |  raw |
  | [TabSeparatedRawWithNamesAndTypes](/zh/reference/formats/TabSeparated/TabSeparatedRawWithNamesAndTypes)             |  raw |  raw |
  | [Template](/zh/reference/formats/Template/Template)                                                                 |  raw |  raw |
  | [TemplateIgnoreSpaces](/zh/reference/formats/Template/TemplateIgnoreSpaces)                                         |  raw |   -  |
  | [CSV](/zh/reference/formats/CSV/CSV)                                                                                |  raw |  raw |
  | [CSVWithNames](/zh/reference/formats/CSV/CSVWithNames)                                                              |  raw |  raw |
  | [CSVWithNamesAndTypes](/zh/reference/formats/CSV/CSVWithNamesAndTypes)                                              |  raw |  raw |
  | [CustomSeparated](/zh/reference/formats/CustomSeparated/CustomSeparated)                                            |  raw |  raw |
  | [CustomSeparatedWithNames](/zh/reference/formats/CustomSeparated/CustomSeparatedWithNames)                          |  raw |  raw |
  | [CustomSeparatedWithNamesAndTypes](/zh/reference/formats/CustomSeparated/CustomSeparatedWithNamesAndTypes)          |  raw |  raw |
  | [SQLInsert](/zh/reference/formats/SQLInsert)                                                                        |   -  |  raw |
  | [Values](/zh/reference/formats/Values)                                                                              |  raw |  raw |
  | [Vertical](/zh/reference/formats/Vertical)                                                                          |   -  |  raw |
  | [JSON](/zh/reference/formats/JSON/JSON)                                                                             |  raw |  raw |
  | [JSONAsString](/zh/reference/formats/JSON/JSONAsString)                                                             |  raw |   -  |
  | [JSONAsObject](/zh/reference/formats/JSON/JSONAsObject)                                                             |  raw |   -  |
  | [JSONStrings](/zh/reference/formats/JSON/JSONStrings)                                                               |  raw |  raw |
  | [JSONColumns](/zh/reference/formats/JSON/JSONColumns)                                                               |  raw |  raw |
  | [JSONColumnsWithMetadata](/zh/reference/formats/JSON/JSONColumnsWithMetadata)                                       |  raw |  raw |
  | [JSONCompact](/zh/reference/formats/JSON/JSONCompact)                                                               |  raw |  raw |
  | [JSONCompactStrings](/zh/reference/formats/JSON/JSONCompactStrings)                                                 |   -  |  raw |
  | [JSONCompactColumns](/zh/reference/formats/JSON/JSONCompactColumns)                                                 |  raw |  raw |
  | [JSONEachRow](/zh/reference/formats/JSON/JSONEachRow)                                                               |  raw |  raw |
  | [PrettyJSONEachRow](/zh/reference/formats/JSON/PrettyJSONEachRow)                                                   |   -  |  raw |
  | [JSONEachRowWithProgress](/zh/reference/formats/JSON/JSONEachRowWithProgress)                                       |   -  |  raw |
  | [JSONStringsEachRow](/zh/reference/formats/JSON/JSONStringsEachRow)                                                 |  raw |  raw |
  | [JSONStringsEachRowWithProgress](/zh/reference/formats/JSON/JSONStringsEachRowWithProgress)                         |   -  |  raw |
  | [JSONCompactEachRow](/zh/reference/formats/JSON/JSONCompactEachRow)                                                 |  raw |  raw |
  | [JSONCompactEachRowWithNames](/zh/reference/formats/JSON/JSONCompactEachRowWithNames)                               |  raw |  raw |
  | [JSONCompactEachRowWithNamesAndTypes](/zh/reference/formats/JSON/JSONCompactEachRowWithNamesAndTypes)               |  raw |  raw |
  | [JSONCompactStringsEachRow](/zh/reference/formats/JSON/JSONCompactStringsEachRow)                                   |  raw |  raw |
  | [JSONCompactStringsEachRowWithNames](/zh/reference/formats/JSON/JSONCompactStringsEachRowWithNames)                 |  raw |  raw |
  | [JSONCompactStringsEachRowWithNamesAndTypes](/zh/reference/formats/JSON/JSONCompactStringsEachRowWithNamesAndTypes) |  raw |  raw |
  | [JSONObjectEachRow](/zh/reference/formats/JSON/JSONObjectEachRow)                                                   |  raw |  raw |
  | [BSONEachRow](/zh/reference/formats/BSONEachRow)                                                                    |  raw |  raw |
  | [TSKV](/zh/reference/formats/TabSeparated/TSKV)                                                                     |  raw |  raw |
  | [Pretty](/zh/reference/formats/Pretty/Pretty)                                                                       |   -  |  raw |
  | [PrettyNoEscapes](/zh/reference/formats/Pretty/PrettyNoEscapes)                                                     |   -  |  raw |
  | [PrettyMonoBlock](/zh/reference/formats/Pretty/PrettyMonoBlock)                                                     |   -  |  raw |
  | [PrettyNoEscapesMonoBlock](/zh/reference/formats/Pretty/PrettyNoEscapesMonoBlock)                                   |   -  |  raw |
  | [PrettyCompact](/zh/reference/formats/Pretty/PrettyCompact)                                                         |   -  |  raw |
  | [PrettyCompactNoEscapes](/zh/reference/formats/Pretty/PrettyCompactNoEscapes)                                       |   -  |  raw |
  | [PrettyCompactMonoBlock](/zh/reference/formats/Pretty/PrettyCompactMonoBlock)                                       |   -  |  raw |
  | [PrettyCompactNoEscapesMonoBlock](/zh/reference/formats/Pretty/PrettyCompactNoEscapesMonoBlock)                     |   -  |  raw |
  | [PrettySpace](/zh/reference/formats/Pretty/PrettySpace)                                                             |   -  |  raw |
  | [PrettySpaceNoEscapes](/zh/reference/formats/Pretty/PrettySpaceNoEscapes)                                           |   -  |  raw |
  | [PrettySpaceMonoBlock](/zh/reference/formats/Pretty/PrettySpaceMonoBlock)                                           |   -  |  raw |
  | [PrettySpaceNoEscapesMonoBlock](/zh/reference/formats/Pretty/PrettySpaceNoEscapesMonoBlock)                         |   -  |  raw |
  | [Prometheus](/zh/reference/formats/Prometheus)                                                                      |   -  |  raw |
  | [Protobuf](/zh/reference/formats/Protobuf/Protobuf)                                                                 |  raw |  raw |
  | [ProtobufSingle](/zh/reference/formats/Protobuf/ProtobufSingle)                                                     |  raw |  raw |
  | [ProtobufList](/zh/reference/formats/Protobuf/ProtobufList)                                                         |  raw |  raw |
  | [Avro](/zh/reference/formats/Avro/Avro)                                                                             |  raw |  raw |
  | [AvroConfluent](/zh/reference/formats/Avro/AvroConfluent)                                                           |  raw |   -  |
  | [Parquet](/zh/reference/formats/Parquet/Parquet)                                                                    |  raw |  raw |
  | [ParquetMetadata](/zh/reference/formats/Parquet/ParquetMetadata)                                                    |  raw |   -  |
  | [Arrow](/zh/reference/formats/Arrow/Arrow)                                                                          |  raw |  raw |
  | [ArrowStream](/zh/reference/formats/Arrow/ArrowStream)                                                              |  raw |  raw |
  | [ORC](/zh/reference/formats/ORC)                                                                                    |  raw |  raw |
  | [One](/zh/reference/formats/One)                                                                                    |  raw |   -  |
  | [Npy](/zh/reference/formats/Npy)                                                                                    |  raw |  raw |
  | [RowBinary](/zh/reference/formats/RowBinary/RowBinary)                                                              | full | full |
  | [RowBinaryWithNames](/zh/reference/formats/RowBinary/RowBinaryWithNamesAndTypes)                                    | full | full |
  | [RowBinaryWithNamesAndTypes](/zh/reference/formats/RowBinary/RowBinaryWithNamesAndTypes)                            | full | full |
  | [RowBinaryWithDefaults](/zh/reference/formats/RowBinary/RowBinaryWithDefaults)                                      | full |   -  |
  | [Native](/zh/reference/formats/Native)                                                                              | full |  raw |
  | [Null](/zh/reference/formats/Null)                                                                                  |   -  |  raw |
  | [XML](/zh/reference/formats/XML)                                                                                    |   -  |  raw |
  | [CapnProto](/zh/reference/formats/CapnProto)                                                                        |  raw |  raw |
  | [LineAsString](/zh/reference/formats/LineAsString/LineAsString)                                                     |  raw |  raw |
  | [Regexp](/zh/reference/formats/Regexp)                                                                              |  raw |   -  |
  | [RawBLOB](/zh/reference/formats/RawBLOB)                                                                            |  raw |  raw |
  | [MsgPack](/zh/reference/formats/MsgPack)                                                                            |  raw |  raw |
  | [MySQLDump](/zh/reference/formats/MySQLDump)                                                                        |  raw |   -  |
  | [DWARF](/zh/reference/formats/DWARF)                                                                                |  raw |   -  |
  | [Markdown](/zh/reference/formats/Markdown)                                                                          |   -  |  raw |
  | [Form](/zh/reference/formats/Form)                                                                                  |  raw |   -  |

  ## 插入 API

  ### insert(String tableName, InputStream data, ClickHouseFormat format)

  以指定格式接受字节 `InputStream` 形式的数据。`data` 须以 `format` 指定的格式进行编码。

  **签名**

  ```java theme={null}
  CompletableFuture<InsertResponse> insert(String tableName, InputStream data, ClickHouseFormat format, InsertSettings settings)
  CompletableFuture<InsertResponse> insert(String tableName, InputStream data, ClickHouseFormat format)
  ```

  **参数**

  `tableName` - 目标表名称。

  `data` - 已编码数据的输入 stream。

  `format` - 数据编码所使用的格式。

  `settings` - 请求设置。

  **返回值**

  `InsertResponse` 类型的 Future——操作结果及附加信息，例如服务器端指标。

  **示例**

  ```java showLineNumbers theme={null}
  try (InputStream dataStream = getDataStream()) {
      try (InsertResponse response = client.insert(TABLE_NAME, dataStream, ClickHouseFormat.JSONEachRow,
              insertSettings).get(3, TimeUnit.SECONDS)) {

          log.info("Insert finished: {} rows written", response.getMetrics().getMetric(ServerMetrics.NUM_ROWS_WRITTEN).getLong());
      } catch (Exception e) {
          log.error("Failed to write JSONEachRow data", e);
          throw new RuntimeException(e);
      }
  }
  ```

  ### insert(String tableName, List\<?> data, InsertSettings settings)

  向数据库发送写请求。对象列表将被转换为高效格式后发送至服务器。列表项的类需要预先通过 `register(Class, TableSchema)` 方法注册。

  **签名**

  ```java theme={null}
  client.insert(String tableName, List<?> data, InsertSettings settings)
  client.insert(String tableName, List<?> data)
  ```

  **参数**

  `tableName` - 目标表的名称。

  `data` - 集合 DTO (数据传输对象) 对象。

  `settings` - 请求设置。

  **返回值**

  `InsertResponse` 类型的 Future——包含操作结果及服务端指标等附加信息。

  **示例**

  ```java showLineNumbers theme={null}
  // 重要步骤（仅执行一次）——注册类，以便根据表的 schema 预编译对象序列化器。
  client.register(ArticleViewEvent.class, client.getTableSchema(TABLE_NAME));

  List<ArticleViewEvent> events = loadBatch();

  try (InsertResponse response = client.insert(TABLE_NAME, events).get()) {
      // 处理响应，完成后响应将被关闭，处理该请求的连接也将被释放。
  }
  ```

  ### InsertSettings

  插入操作的配置选项。

  **配置方法**

  | 方法                                              | 说明                                                  |
  | ----------------------------------------------- | --------------------------------------------------- |
  | `setQueryId(String queryId)`                    | 设置要分配给该操作的查询 ID。默认值：`null`。                         |
  | `setDeduplicationToken(String token)`           | 设置去重令牌。该令牌会发送到服务器，可用于标识查询。默认值：`null`。               |
  | `setInputStreamCopyBufferSize(int size)`        | 复制缓冲区大小。该缓冲区在写入操作期间用于将数据从用户提供的输入流复制到输出流。默认值：`8196`。 |
  | `serverSetting(String name, String value)`      | 为某个操作设置单个服务器级设置项。                                   |
  | `serverSetting(String name, Collection values)` | 为某项操作设置一个具有多个值的服务器设置。集合中的项应为 `String` 值。            |
  | `setDBRoles(Collection dbRoles)`                | 设置在执行操作前生效的 DB 角色。集合中的项应为 `String` 值。               |
  | `setOption(String option, Object value)`        | 以原始格式设置一个配置选项。这不是服务器级设置项。                           |

  ### InsertResponse

  保存插入操作结果的响应对象。仅在客户端收到服务器响应时可用。

  <Note>
    应尽快关闭此对象以释放连接，因为在完全读取前一个响应的所有数据之前，该连接无法重新使用。
  </Note>

  | 方法                              | 说明                                      |
  | ------------------------------- | --------------------------------------- |
  | `OperationMetrics getMetrics()` | 返回包含操作指标的对象。                            |
  | `String getQueryId()`           | 返回该操作的查询 ID，该 ID 由应用程序通过操作设置指定，或由服务器分配。 |

  ## 查询 API

  ### query(String sqlQuery)

  按原样发送 `sqlQuery`。响应格式由查询设置决定。`QueryResponse` 将持有对响应 stream 的引用，该 stream 应由支持相应格式的读取器消费。

  **签名**

  ```java theme={null}
  CompletableFuture<QueryResponse> query(String sqlQuery, QuerySettings settings)
  CompletableFuture<QueryResponse> query(String sqlQuery)
  ```

  **参数**

  `sqlQuery` - 单条 SQL 语句。查询将按原样发送至服务器。

  `settings` - 请求设置。

  **返回值**

  `QueryResponse` 类型的 Future——包含结果数据集及服务端指标等附加信息。消费完数据集后，应关闭 Response 对象。

  **示例**

  ```java theme={null}
  final String sql = "select * from " + TABLE_NAME + " where title <> '' limit 10";

  // 默认格式为 RowBinaryWithNamesAndTypesFormatReader，因此 reader 包含所有列的信息
  try (QueryResponse response = client.query(sql).get(3, TimeUnit.SECONDS);) {

      // 创建 reader 以便捷地访问数据
      ClickHouseBinaryFormatReader reader = client.newBinaryFormatReader(response);

      while (reader.hasNext()) {
          reader.next(); // 从 stream 中读取下一条记录并解析

          // 获取值
          double id = reader.getDouble("id");
          String title = reader.getString("title");
          String url = reader.getString("url");

          // 收集数据
      }
  } catch (Exception e) {
      log.error("Failed to read data", e);
  }

  // 将业务逻辑放在读取块之外，以尽快释放 HTTP 连接。
  ```

  ### query(String sqlQuery, Map\<String, Object> queryParams, QuerySettings settings)

  按原样发送 `sqlQuery`，同时发送查询参数，以便服务器编译 SQL 表达式。

  **签名**

  ```java theme={null}
  CompletableFuture<QueryResponse> query(String sqlQuery, Map<String, Object> queryParams, QuerySettings settings)
  ```

  **参数**

  `sqlQuery` - 带占位符 `{}` 的 SQL 表达式。

  `queryParams` - 用于在服务器端补全 SQL 表达式的变量映射。

  `settings` - 请求设置。

  **返回值**

  `QueryResponse` 类型的 Future——包含结果数据集及服务端指标等附加信息。消费完数据集后，应关闭 Response 对象。

  **示例**

  ```java showLineNumbers theme={null}
  // 定义参数。这些参数将随请求一起发送到服务器。
  Map<String, Object> queryParams = new HashMap<>();
  queryParams.put("param1", 2);

  try (QueryResponse response =
          client.query("SELECT * FROM " + table + " WHERE col1 >= {param1:UInt32}", queryParams, new QuerySettings()).get()) {

      // 创建读取器以便捷地访问数据
      ClickHouseBinaryFormatReader reader = client.newBinaryFormatReader(response);

      while (reader.hasNext()) {
          reader.next(); // 从 stream 中读取下一条记录并解析

          // 读取数据
      }

  } catch (Exception e) {
      log.error("Failed to read data", e);
  }
  ```

  ### queryAll(String sqlQuery)

  以 `RowBinaryWithNamesAndTypes` 格式查询数据，并以集合形式返回结果。读取性能与使用 reader 时相同，但需要占用更多内存来存储完整的数据集。

  **签名**

  ```java theme={null}
  List<GenericRecord> queryAll(String sqlQuery)
  ```

  **参数**

  `sqlQuery` - 用于从服务器查询数据的 SQL 表达式。

  **返回值**

  完整数据集，由一组 `GenericRecord` 对象列表表示，以行方式访问结果数据。

  **示例**

  ```java showLineNumbers theme={null}
  try {
      log.info("Reading whole table and process record by record");
      final String sql = "select * from " + TABLE_NAME + " where title <> ''";

      // 读取完整结果集并逐条处理
      client.queryAll(sql).forEach(row -> {
          double id = row.getDouble("id");
          String title = row.getString("title");
          String url = row.getString("url");

          log.info("id: {}, title: {}, url: {}", id, title, url);
      });
  } catch (Exception e) {
      log.error("Failed to read data", e);
  }
  ```

  ### QuerySettings

  查询操作的配置选项。

  **配置方法**

  | 方法                                                | 说明                                                                                                           |
  | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
  | `setQueryId(String queryId)`                      | 设置将分配给该操作的查询 ID。                                                                                             |
  | `setFormat(ClickHouseFormat format)`              | 设置响应格式。完整列表请参见 `RowBinaryWithNamesAndTypes`。                                                                 |
  | `setMaxExecutionTime(Integer maxExecutionTime)`   | 设置该操作在服务器端的执行时间。不会影响读取超时。                                                                                    |
  | `waitEndOfQuery(Boolean waitEndOfQuery)`          | 请求服务器在发送响应前等待查询结束。                                                                                           |
  | `setUseServerTimeZone(Boolean useServerTimeZone)` | 将使用服务器时区 (参见客户端配置) 来解析操作结果中的日期/时间类型。默认为 `false`。                                                             |
  | `setUseTimeZone(String timeZone)`                 | 请求服务器使用 `timeZone` 进行时间转换。请参见 [session\_timezone](/zh/reference/settings/session-settings#session_timezone)。 |
  | `serverSetting(String name, String value)`        | 为该操作设置单个服务器级设置。                                                                                              |
  | `serverSetting(String name, Collection values)`   | 为某个操作设置单个服务器设置项的多个值。集合中的项应为 `String` 值。                                                                      |
  | `setDBRoles(Collection dbRoles)`                  | 设置在执行操作前要启用的 DB 角色。集合中的项应为 `String` 值。                                                                       |
  | `setOption(String option, Object value)`          | 以原始格式设置配置选项。这不是服务器级别的设置。                                                                                     |

  ### QueryResponse

  保存查询执行结果的响应对象。仅当客户端收到来自服务器的响应时，该对象才可用。

  <Note>
    应尽快关闭此对象以释放连接，因为在完全读取前一个响应的所有数据之前，该连接无法复用。
  </Note>

  | 方法                              | 描述                                         |
  | ------------------------------- | ------------------------------------------ |
  | `ClickHouseFormat getFormat()`  | 返回响应中数据采用的编码格式。                            |
  | `InputStream getInputStream()`  | 返回采用指定格式的未压缩数据字节流。                         |
  | `OperationMetrics getMetrics()` | 返回包含操作指标的对象。                               |
  | `String getQueryId()`           | 返回该操作的查询 ID，该 ID 由应用程序分配 (通过操作设置) 或由服务器分配。 |
  | `TimeZone getTimeZone()`        | 返回处理响应中的 Date/DateTime 类型时应使用的时区。          |

  ### 示例

  * 示例代码可在[仓库](https://github.com/ClickHouse/clickhouse-java/tree/main/examples/client-v2)中找到
  * 参考 Spring Service 的[实现](https://github.com/ClickHouse/clickhouse-java/tree/main/examples/demo-service)

  ## 通用 API

  ### getTableSchema(String table)

  拉取 `table` 的表 schema。

  **签名**

  ```java theme={null}
  TableSchema getTableSchema(String table)
  TableSchema getTableSchema(String table, String database)
  ```

  **参数**

  `table` - 需要拉取 schema 数据的表名。

  `database` - 目标表所在的数据库。

  **返回值**

  返回一个包含表列列表的 `TableSchema` 对象。

  ### getTableSchemaFromQuery(String sql)

  从 SQL 语句中拉取 schema。

  **签名**

  ```java theme={null}
  TableSchema getTableSchemaFromQuery(String sql)
  ```

  **参数**

  `sql` - 需要返回其 schema 的 "SELECT" SQL 语句。

  **返回值**

  返回一个 `TableSchema` 对象，其列与 `sql` 表达式相匹配。

  ### TableSchema

  ### register(Class\<?> clazz, TableSchema schema)

  为 Java 类编译序列化与反序列化 layer，以便通过 `schema` 进行数据读写。该 method 将为 getter/setter 对及其对应列创建序列化器和反序列化器。
  列的匹配通过从方法名中提取列名来实现。例如，`getFirstName` 对应的列为 `first_name` 或 `firstname`。

  **签名**

  ```java theme={null}
  void register(Class<?> clazz, TableSchema schema)
  ```

  **参数**

  `clazz` - 表示用于读取/写入数据的 POJO 的类。

  `schema` - 用于与 POJO 属性进行匹配的数据 schema。

  **示例**

  ```java showLineNumbers theme={null}
  client.register(ArticleViewEvent.class, client.getTableSchema(TABLE_NAME));
  ```

  ## 使用示例

  完整的示例代码存放在代码仓库的 'example\` [文件夹](https://github.com/ClickHouse/clickhouse-java/tree/main/examples)中：

  * [client-v2](https://github.com/ClickHouse/clickhouse-java/tree/main/examples/client-v2) - 主要示例。
  * [demo-service](https://github.com/ClickHouse/clickhouse-java/tree/main/examples/demo-service) - 展示如何在 Spring Boot 应用程序中使用该客户端的示例。
  * [demo-kotlin-service](https://github.com/ClickHouse/clickhouse-java/tree/main/examples/demo-kotlin-service) - 在 Ktor (Kotlin) 应用中使用客户端的示例。

  ## 读取数据

  读取数据有两种常见方式：

  * 返回底层 `QueryResponse` 对象的 `query()` 方法，该对象包含带有数据的 `InputStream`。通常会结合 `ClickHouseBinaryFormatReader` 用于流式读取，但
    也可搭配任何其他自定义 reader 实现使用。`QueryResponse` 还提供对结果集元数据和指标的访问。
  * `queryAll()` 方法，并使用 `GenericRecord` 以便更方便地访问行。在这种情况下，整个结果集都会加载到内存中。
  * 返回 `com.clickhouse.client.api.query.Records` 的 `queryRecords()` 方法——它是一个用于遍历 `GenericRecord` 对象的迭代器。该方法采用流式方式
    (不会将任何数据加载到内存中) ，并通过 `GenericRecord` 访问数据。

  **注意：** 流式方法要求快速读取，否则可能导致服务器写入超时，因为数据是直接从网络流中读取的。

  ### 读取 Arrays

  **`ClickHouseBinaryFormatReader` 方法**

  * `getList(...)` - 将任意 `Array(...)` 读取为 `List<T>`。这是灵活类型读取的默认推荐选择。支持嵌套数组。
  * `getByteArray(...)`, `getShortArray(...)`, `getIntArray(...)`, `getLongArray(...)`, `getFloatArray(...)`, `getDoubleArray(...)`, `getBooleanArray(...)` - 最适合用于包含与基本类型兼容值的一维数组。
  * `getStringArray(...)` - 用于 `Array(String)` (以及以名称形式表示的枚举值) 。
  * `getObjectArray(...)` - 适用于任意 `Array(...)` 元素类型的通用选项，包括嵌套数组。可用于读取包含 Nullable 值和嵌套数组的数组。

  所有方法均支持基于索引和基于名称的重载。索引从 1 开始计数。基于索引的方式可直接访问列。
  基于名称的方法每次调用时均需执行索引查找。

  ```java theme={null}
  try (QueryResponse response = client.query("SELECT * FROM my_table").get()) {
      ClickHouseBinaryFormatReader reader = client.newBinaryFormatReader(response);
      while (reader.next() != null) {
          
          Object[] uint64 = reader.getObjectArray("uint64_arr"); // Array(UInt64) -> BigInteger[]
          Object[] arr2d = reader.getObjectArray("arr2d");       // Array(Array(Int64)) -> Object[]

          // 嵌套数组以嵌套 Object[] 的形式返回：
          Object[] firstInner = (Object[]) arr2d[0];
          Long firstValue = (Long) firstInner[0];
      }
  }
  ```

  **`GenericRecord` 方法**

  * `getList(...)` - 将任意 `Array(...)` 读取为 `List<T>`。这是进行灵活类型读取时的默认优选。支持嵌套数组。
  * `getByteArray(...)`, `getShortArray(...)`, `getIntArray(...)`, `getLongArray(...)`, `getFloatArray(...)`, `getDoubleArray(...)`, `getBooleanArray(...)` - 最适合用于包含与基本类型兼容的值的一维数组。
  * `getStringArray(...)` - 用于 `Array(String)` (以及以名称形式表示的枚举值) 。
  * `getObjectArray(...)` - 适用于任何 `Array(...)` 元素类型 (包括嵌套数组) 的通用选项。用于读取包含可为 NULL 的值及嵌套数组的数组。

  所有方法均支持基于索引和基于名称的重载。索引从 1 开始计数。基于索引的方式可直接访问列。
  基于名称的方法每次调用时均需进行索引查找。

  ```java theme={null}
  try (QueryResponse response = client.query("SELECT * FROM my_table").get()) {
      List<GenericRecord> rows = client.queryAll(
          "SELECT int_arr, arr2d_nullable FROM test_arrays ORDER BY id");

      for (GenericRecord row : rows) {
          Object[] intArr = row.getObjectArray("int_arr");                 // Array(Int32) -> Integer[]
          Object[] arr2d = row.getObjectArray("arr2d_nullable");           // Array(Array(Nullable(Int32)))

          Object[] inner = (Object[]) arr2d[0];
          Object maybeNull = inner[1]; // may be null
      }
  }
  ```

  ## 迁移指南

  旧版客户端 (V1) 以 `com.clickhouse.client.ClickHouseClient#builder` 作为起点。新版客户端 (V2) 采用类似的模式，使用 `com.clickhouse.client.api.Client.Builder`。主要区别如下：

  * 未使用服务加载器来获取具体实现。`com.clickhouse.client.api.Client` 是一个门面类，未来可适配各种实现。
  * 配置来源更少：一类提供给构建器，另一类在操作设置 (`QuerySettings`、`InsertSettings`) 中。先前版本会为每个节点分别配置，并且在某些情况下会加载
    环境变量。

  ### 配置参数匹配

  V1 中有 3 个与配置相关的枚举类：

  * `com.clickhouse.client.config.ClickHouseDefaults` - 在大多数情况下都需要设置的配置参数，例如 `USER` 和 `PASSWORD`。
  * `com.clickhouse.client.config.ClickHouseClientOption` - 客户端特有的配置参数，例如 `HEALTH_CHECK_INTERVAL`。
  * `com.clickhouse.client.http.config.ClickHouseHttpOption` - HTTP 接口专用的配置参数，例如 `RECEIVE_QUERY_PROGRESS`。

  这些设计的初衷是对参数进行分组并实现清晰的隔离。然而在某些情况下，这反而造成了混淆 (例如，`com.clickhouse.client.config.ClickHouseDefaults#ASYNC` 与
  `com.clickhouse.client.config.ClickHouseClientOption#ASYNC` 之间究竟有何区别？) 。新的 V2 客户端以 `com.clickhouse.client.api.Client.Builder` 作为所有可用客户端配置选项的统一字典。所有配置参数名称均列于
  `com.clickhouse.client.api.ClientConfigProperties` 中。

  下表列出了新客户端中支持的旧选项及其新含义。

  **图例：** ✔ = 支持，✗ = 已丢弃

  <Tabs>
    <Tab title="连接与认证">
      | V1 配置                                                                            | V2 构建器方法                                    | 备注          |
      | -------------------------------------------------------------------------------- | ------------------------------------------- | ----------- |
      | `ClickHouseDefaults#HOST`                                                        | `Client.Builder#addEndpoint`                |             |
      | `ClickHouseDefaults#PROTOCOL`                                                    | ✗                                           | V2 仅支持 HTTP |
      | `ClickHouseDefaults#DATABASE`<br />`ClickHouseClientOption#DATABASE`             | `Client.Builder#setDefaultDatabase`         |             |
      | `ClickHouseDefaults#USER`                                                        | `Client.Builder#setUsername`                |             |
      | `ClickHouseDefaults#PASSWORD`                                                    | `Client.Builder#setPassword`                |             |
      | `ClickHouseClientOption#CONNECTION_TIMEOUT`                                      | `Client.Builder#setConnectTimeout`          |             |
      | `ClickHouseClientOption#CONNECTION_TTL`                                          | `Client.Builder#setConnectionTTL`           |             |
      | `ClickHouseHttpOption#MAX_OPEN_CONNECTIONS`                                      | `Client.Builder#setMaxConnections`          |             |
      | `ClickHouseHttpOption#KEEP_ALIVE`<br />`ClickHouseHttpOption#KEEP_ALIVE_TIMEOUT` | `Client.Builder#setKeepAliveTimeout`        |             |
      | `ClickHouseHttpOption#CONNECTION_REUSE_STRATEGY`                                 | `Client.Builder#setConnectionReuseStrategy` |             |
      | `ClickHouseHttpOption#USE_BASIC_AUTHENTICATION`                                  | `Client.Builder#useHTTPBasicAuth`           |             |
    </Tab>

    <Tab title="SSL 与安全">
      | V1 配置                                                  | V2 构建器方法                                  | 备注                                       |
      | ------------------------------------------------------ | ----------------------------------------- | ---------------------------------------- |
      | `ClickHouseDefaults#SSL_CERTIFICATE_TYPE`              | ✗                                         |                                          |
      | `ClickHouseDefaults#SSL_KEY_ALGORITHM`                 | ✗                                         |                                          |
      | `ClickHouseDefaults#SSL_PROTOCOL`                      | ✗                                         |                                          |
      | `ClickHouseClientOption#SSL`                           | ✗                                         | 参见 `Client.Builder#addEndpoint`          |
      | `ClickHouseClientOption#SSL_MODE`                      | ✗                                         |                                          |
      | `ClickHouseClientOption#SSL_ROOT_CERTIFICATE`          | `Client.Builder#setRootCertificate`       | 应使用 `useSSLAuthentication` 启用 SSL 身份验证   |
      | `ClickHouseClientOption#SSL_CERTIFICATE`               | `Client.Builder#setClientCertificate`     |                                          |
      | `ClickHouseClientOption#SSL_KEY`                       | `Client.Builder#setClientKey`             |                                          |
      | `ClickHouseClientOption#KEY_STORE_TYPE`                | `Client.Builder#setSSLTrustStoreType`     |                                          |
      | `ClickHouseClientOption#TRUST_STORE`                   | `Client.Builder#setSSLTrustStore`         |                                          |
      | `ClickHouseClientOption#KEY_STORE_PASSWORD`            | `Client.Builder#setSSLTrustStorePassword` |                                          |
      | `ClickHouseClientOption#SSL_SOCKET_SNI`                | `Client.Builder#sslSocketSNI`             |                                          |
      | `ClickHouseClientOption#CUSTOM_SOCKET_FACTORY`         | ✗                                         |                                          |
      | `ClickHouseClientOption#CUSTOM_SOCKET_FACTORY_OPTIONS` | ✗                                         | 参见 `Client.Builder#sslSocketSNI` 来设置 SNI |
    </Tab>

    <Tab title="套接字选项">
      | V1 配置                                       | V2 构建器方法                               | 说明 |
      | ------------------------------------------- | -------------------------------------- | -- |
      | `ClickHouseClientOption#SOCKET_TIMEOUT`     | `Client.Builder#setSocketTimeout`      |    |
      | `ClickHouseClientOption#SOCKET_REUSEADDR`   | `Client.Builder#setSocketReuseAddress` |    |
      | `ClickHouseClientOption#SOCKET_KEEPALIVE`   | `Client.Builder#setSocketKeepAlive`    |    |
      | `ClickHouseClientOption#SOCKET_LINGER`      | `Client.Builder#setSocketLinger`       |    |
      | `ClickHouseClientOption#SOCKET_IP_TOS`      | ✗                                      |    |
      | `ClickHouseClientOption#SOCKET_TCP_NODELAY` | `Client.Builder#setSocketTcpNodelay`   |    |
      | `ClickHouseClientOption#SOCKET_RCVBUF`      | `Client.Builder#setSocketRcvbuf`       |    |
      | `ClickHouseClientOption#SOCKET_SNDBUF`      | `Client.Builder#setSocketSndbuf`       |    |
    </Tab>

    <Tab title="压缩">
      | V1 配置                                         | V2 构建器方法                                | 注释                                         |
      | --------------------------------------------- | --------------------------------------- | ------------------------------------------ |
      | `ClickHouseClientOption#COMPRESS`             | `Client.Builder#compressServerResponse` | 另见 `useHttpCompression`                    |
      | `ClickHouseClientOption#DECOMPRESS`           | `Client.Builder#compressClientRequest`  | 另见 `useHttpCompression`                    |
      | `ClickHouseClientOption#COMPRESS_ALGORITHM`   | ✗                                       | 非 HTTP 使用 `LZ4`。HTTP 使用 `Accept-Encoding`  |
      | `ClickHouseClientOption#DECOMPRESS_ALGORITHM` | ✗                                       | 非 HTTP 使用 `LZ4`。HTTP 使用 `Content-Encoding` |
      | `ClickHouseClientOption#COMPRESS_LEVEL`       | ✗                                       |                                            |
      | `ClickHouseClientOption#DECOMPRESS_LEVEL`     | ✗                                       |                                            |
    </Tab>

    <Tab title="代理">
      | V1 配置                                   | V2 构建器方法                             | 注释 |
      | --------------------------------------- | ------------------------------------ | -- |
      | `ClickHouseClientOption#PROXY_TYPE`     | `Client.Builder#addProxy`            |    |
      | `ClickHouseClientOption#PROXY_HOST`     | `Client.Builder#addProxy`            |    |
      | `ClickHouseClientOption#PROXY_PORT`     | `Client.Builder#addProxy`            |    |
      | `ClickHouseClientOption#PROXY_USERNAME` | `Client.Builder#setProxyCredentials` |    |
      | `ClickHouseClientOption#PROXY_PASSWORD` | `Client.Builder#setProxyCredentials` |    |
    </Tab>

    <Tab title="超时与重试">
      | V1 配置                                           | V2 Builder 方法                        | 注释                   |
      | ----------------------------------------------- | ------------------------------------ | -------------------- |
      | `ClickHouseClientOption#MAX_EXECUTION_TIME`     | `Client.Builder#setExecutionTimeout` |                      |
      | `ClickHouseClientOption#RETRY`                  | `Client.Builder#setMaxRetries`       | 另见 `retryOnFailures` |
      | `ClickHouseHttpOption#AHC_RETRY_ON_FAILURE`     | `Client.Builder#retryOnFailures`     |                      |
      | `ClickHouseClientOption#FAILOVER`               | ✗                                    |                      |
      | `ClickHouseClientOption#REPEAT_ON_SESSION_LOCK` | ✗                                    |                      |
      | `ClickHouseClientOption#SESSION_ID`             | ✗                                    |                      |
      | `ClickHouseClientOption#SESSION_CHECK`          | ✗                                    |                      |
      | `ClickHouseClientOption#SESSION_TIMEOUT`        | ✗                                    |                      |
    </Tab>

    <Tab title="时区">
      | V1 配置项                                                                               | V2 构建器方法                           | 注释 |
      | ------------------------------------------------------------------------------------ | ---------------------------------- | -- |
      | `ClickHouseDefaults#SERVER_TIME_ZONE`<br />`ClickHouseClientOption#SERVER_TIME_ZONE` | `Client.Builder#setServerTimeZone` |    |
      | `ClickHouseClientOption#USE_SERVER_TIME_ZONE`                                        | `Client.Builder#useServerTimeZone` |    |
      | `ClickHouseClientOption#USE_SERVER_TIME_ZONE_FOR_DATES`                              |                                    |    |
      | `ClickHouseClientOption#USE_TIME_ZONE`                                               | `Client.Builder#useTimeZone`       |    |
    </Tab>

    <Tab title="缓冲区与性能">
      | V1 配置                                           | V2 构建器方法                                    | 说明 |
      | ----------------------------------------------- | ------------------------------------------- | -- |
      | `ClickHouseClientOption#BUFFER_SIZE`            | `Client.Builder#setClientNetworkBufferSize` |    |
      | `ClickHouseClientOption#BUFFER_QUEUE_VARIATION` | ✗                                           |    |
      | `ClickHouseClientOption#READ_BUFFER_SIZE`       | ✗                                           |    |
      | `ClickHouseClientOption#WRITE_BUFFER_SIZE`      | ✗                                           |    |
      | `ClickHouseClientOption#REQUEST_CHUNK_SIZE`     | ✗                                           |    |
      | `ClickHouseClientOption#REQUEST_BUFFERING`      | ✗                                           |    |
      | `ClickHouseClientOption#RESPONSE_BUFFERING`     | ✗                                           |    |
      | `ClickHouseClientOption#MAX_BUFFER_SIZE`        | ✗                                           |    |
      | `ClickHouseClientOption#MAX_QUEUED_BUFFERS`     | ✗                                           |    |
      | `ClickHouseClientOption#MAX_QUEUED_REQUESTS`    | ✗                                           |    |
      | `ClickHouseClientOption#REUSE_VALUE_WRAPPER`    | ✗                                           |    |
    </Tab>

    <Tab title="线程与异步">
      | V1 配置                                                          | V2 构建器方法                          | 备注                              |
      | -------------------------------------------------------------- | --------------------------------- | ------------------------------- |
      | `ClickHouseDefaults#ASYNC`<br />`ClickHouseClientOption#ASYNC` | `Client.Builder#useAsyncRequests` |                                 |
      | `ClickHouseDefaults#MAX_SCHEDULER_THREADS`                     | ✗                                 | 参见 `setSharedOperationExecutor` |
      | `ClickHouseDefaults#MAX_THREADS`                               | ✗                                 | 参见 `setSharedOperationExecutor` |
      | `ClickHouseDefaults#THREAD_KEEPALIVE_TIMEOUT`                  | 参见 `setSharedOperationExecutor`   |                                 |
      | `ClickHouseClientOption#MAX_THREADS_PER_CLIENT`                | ✗                                 |                                 |
      | `ClickHouseClientOption#MAX_CORE_THREAD_TTL`                   | ✗                                 |                                 |
    </Tab>

    <Tab title="HTTP 与请求头">
      | V1 配置                                                | V2 构建器方法                       | 注释                                |
      | ---------------------------------------------------- | ------------------------------ | --------------------------------- |
      | `ClickHouseHttpOption#CUSTOM_HEADERS`                | `Client.Builder#httpHeaders`   |                                   |
      | `ClickHouseHttpOption#CUSTOM_PARAMS`                 | ✗                              | 参见 `Client.Builder#serverSetting` |
      | `ClickHouseClientOption#CLIENT_NAME`                 | `Client.Builder#setClientName` |                                   |
      | `ClickHouseHttpOption#CONNECTION_PROVIDER`           | ✗                              |                                   |
      | `ClickHouseHttpOption#DEFAULT_RESPONSE`              | ✗                              |                                   |
      | `ClickHouseHttpOption#SEND_HTTP_CLIENT_ID`           | ✗                              |                                   |
      | `ClickHouseHttpOption#AHC_VALIDATE_AFTER_INACTIVITY` | ✗                              | 使用 Apache Http Client 时始终处于启用状态   |
    </Tab>

    <Tab title="格式与查询">
      | V1 配置                                                            | V2 构建器方法            | 说明                                                                    |
      | ---------------------------------------------------------------- | ------------------- | --------------------------------------------------------------------- |
      | `ClickHouseDefaults#FORMAT`<br />`ClickHouseClientOption#FORMAT` | ✗                   | 已移至操作设置 (`QuerySettings` 和 `InsertSettings`)                          |
      | `ClickHouseClientOption#QUERY_ID`                                | ✗                   | 参见 `QuerySettings` 和 `InsertSettings`                                 |
      | `ClickHouseClientOption#LOG_LEADING_COMMENT`                     | ✗                   | 参见 `QuerySettings#logComment` 和 `InsertSettings#logComment`           |
      | `ClickHouseClientOption#MAX_RESULT_ROWS`                         | ✗                   | 属于服务端设置                                                               |
      | `ClickHouseClientOption#RESULT_OVERFLOW_MODE`                    | ✗                   | 属于服务端设置                                                               |
      | `ClickHouseHttpOption#RECEIVE_QUERY_PROGRESS`                    | ✗                   | 属于服务端设置                                                               |
      | `ClickHouseHttpOption#WAIT_END_OF_QUERY`                         | ✗                   | 属于服务端设置                                                               |
      | `ClickHouseHttpOption#REMEMBER_LAST_SET_ROLES`                   | `Client#setDBRoles` | 现为运行时配置。另请参见 `QuerySettings#setDBRoles` 和 `InsertSettings#setDBRoles` |
    </Tab>

    <Tab title="节点发现与负载均衡">
      | V1 配置                                            | V2 构建器方法 | 注释 |
      | ------------------------------------------------ | -------- | -- |
      | `ClickHouseClientOption#AUTO_DISCOVERY`          | ✗        |    |
      | `ClickHouseClientOption#LOAD_BALANCING_POLICY`   | ✗        |    |
      | `ClickHouseClientOption#LOAD_BALANCING_TAGS`     | ✗        |    |
      | `ClickHouseClientOption#HEALTH_CHECK_INTERVAL`   | ✗        |    |
      | `ClickHouseClientOption#HEALTH_CHECK_METHOD`     | ✗        |    |
      | `ClickHouseClientOption#NODE_DISCOVERY_INTERVAL` | ✗        |    |
      | `ClickHouseClientOption#NODE_DISCOVERY_LIMIT`    | ✗        |    |
      | `ClickHouseClientOption#NODE_CHECK_INTERVAL`     | ✗        |    |
      | `ClickHouseClientOption#NODE_GROUP_SIZE`         | ✗        |    |
      | `ClickHouseClientOption#CHECK_ALL_NODES`         | ✗        |    |
    </Tab>

    <Tab title="杂项">
      | V1 配置                                                                            | V2 构建器方法                          | 注释        |
      | -------------------------------------------------------------------------------- | --------------------------------- | --------- |
      | `ClickHouseDefaults#AUTO_SESSION`                                                | ✗                                 | 会话支持将后续评估 |
      | `ClickHouseDefaults#BUFFERING`                                                   | ✗                                 |           |
      | `ClickHouseDefaults#MAX_REQUESTS`                                                | ✗                                 |           |
      | `ClickHouseDefaults#ROUNDING_MODE`                                               |                                   |           |
      | `ClickHouseDefaults#SERVER_VERSION`<br />`ClickHouseClientOption#SERVER_VERSION` | `Client.Builder#setServerVersion` |           |
      | `ClickHouseDefaults#SRV_RESOLVE`                                                 | ✗                                 |           |
      | `ClickHouseClientOption#CUSTOM_SETTINGS`                                         |                                   |           |
      | `ClickHouseClientOption#PRODUCT_NAME`                                            | ✗                                 | 使用客户端名称   |
      | `ClickHouseClientOption#RENAME_RESPONSE_COLUMN`                                  | ✗                                 |           |
      | `ClickHouseClientOption#SERVER_REVISION`                                         | ✗                                 |           |
      | `ClickHouseClientOption#TRANSACTION_TIMEOUT`                                     | ✗                                 |           |
      | `ClickHouseClientOption#WIDEN_UNSIGNED_TYPES`                                    | ✗                                 |           |
      | `ClickHouseClientOption#USE_BINARY_STRING`                                       | ✗                                 |           |
      | `ClickHouseClientOption#USE_BLOCKING_QUEUE`                                      | ✗                                 |           |
      | `ClickHouseClientOption#USE_COMPILATION`                                         | ✗                                 |           |
      | `ClickHouseClientOption#USE_OBJECTS_IN_ARRAYS`                                   | ✗                                 |           |
      | `ClickHouseClientOption#MAX_MAPPER_CACHE`                                        | ✗                                 |           |
      | `ClickHouseClientOption#MEASURE_REQUEST_TIME`                                    | ✗                                 |           |
    </Tab>
  </Tabs>

  ### 主要差异

  * Client V2 使用更少的专有类，以提高可移植性。例如，V2 可配合 `java.io.InputStream` 的任何实现来
    将数据写入服务器。
  * Client V2 的 `async` 设置默认值为 `off`。这意味着不会额外创建线程，且应用程序对客户端有更强的控制能力。对于绝大多数用例，此设置都应保持为 `off`。启用 `async` 会为每个请求创建一个单独的线程。只有在使用由应用程序控制的
    executor 时，这样做才有意义 (请参见 `com.clickhouse.client.api.Client.Builder#setSharedOperationExecutor`)

  ### 写入数据

  * 可使用 `java.io.InputStream` 的任何实现。支持 V1 `com.clickhouse.data.ClickHouseInputStream`，但不建议使用。
  * 一旦检测到输入流结束，就会进行相应处理。在此之前，应关闭请求的输出流。

  **V1 插入 TSV 格式的数据。**

  ```java theme={null}
  InputStream inData = getInData();
  ClickHouseRequest.Mutation request = client.read(server)
          .write()
          .table(tableName)
          .format(ClickHouseFormat.TSV);
  ClickHouseConfig config = request.getConfig();
  CompletableFuture<ClickHouseResponse> future;
  try (ClickHousePipedOutputStream requestBody = ClickHouseDataStreamFactory.getInstance()
          .createPipedOutputStream(config)) {
      // 启动工作线程，将数据从输入流传输到 ClickHouse
      future = request.data(requestBody.getInputStream()).execute();

      // 将数据从 inData 流复制到 requestBody 流

      // 获取响应前需要先关闭流
      requestBody.close();

      try (ClickHouseResponse response = future.get()) {
          ClickHouseResponseSummary summary = response.getSummary();
          Assert.assertEquals(summary.getWrittenRows(), numRows, "Num of written rows");
      }
  }
  ```

  **V2 插入 TSV 格式数据。**

  ```java theme={null}
  InputStream inData = getInData();
  InsertSettings settings = new InsertSettings().setInputStreamCopyBufferSize(8198 * 2); // 设置复制缓冲区大小
  try (InsertResponse response = client.insert(tableName, inData, ClickHouseFormat.TSV, settings).get(30, TimeUnit.SECONDS)) {

    // 插入操作至此完成

  } catch (Exception e) {
   // 处理异常
  }
  ```

  * 只需调用一个方法。无需另外创建请求对象。
  * 请求体流会在所有数据复制完毕后自动关闭。
  * 现已提供新的底层 API：`com.clickhouse.client.api.Client#insert(java.lang.String, java.util.List<java.lang.String>, com.clickhouse.client.api.DataStreamWriter, com.clickhouse.data.ClickHouseFormat, com.clickhouse.client.api.insert.InsertSettings)`。`com.clickhouse.client.api.DataStreamWriter` 用于实现自定义的数据写入逻辑。例如，从
    队列中读取数据。

  ### 读取数据

  * 默认使用 `RowBinaryWithNamesAndTypes` 格式读取数据。当前在需要进行数据绑定时，仅支持此格式。
  * 可以使用 `List<GenericRecord> com.clickhouse.client.api.Client#queryAll(java.lang.String)` 方法，将数据作为记录集合读取。它会将数据读入内存并释放连接，无需额外处理。`GenericRecord` 提供对数据的访问，并支持一些类型转换。

  ```java theme={null}
  Collection<GenericRecord> records = client.queryAll("SELECT * FROM table");
  for (GenericRecord record : records) {
      int rowId = record.getInteger("rowID");
      String name = record.getString("name");
      LocalDateTime ts = record.getLocalDateTime("ts");
  }
  ```
</View>

<View title="v0.7.x">
  用于通过协议与数据库服务器通信的 Java 客户端库。当前实现仅支持 [HTTP 接口](/zh/concepts/features/interfaces/http)。该库提供自有 API，用于向服务器发送请求。

  <Warning>
    **弃用**

    该库即将弃用。新项目请使用最新的 [Java 客户端](/zh/integrations/language-clients/java/client)
  </Warning>

  ## 设置

  <Tabs>
    <Tab title="Maven">
      ```xml theme={null}
      <!-- https://mvnrepository.com/artifact/com.clickhouse/clickhouse-http-client -->
      <dependency>
          <groupId>com.clickhouse</groupId>
          <artifactId>clickhouse-http-client</artifactId>
          <version>0.7.2</version>
      </dependency>
      ```
    </Tab>

    <Tab title="Gradle (Kotlin)">
      ```kotlin theme={null}
      // https://mvnrepository.com/artifact/com.clickhouse/clickhouse-http-client
      implementation("com.clickhouse:clickhouse-http-client:0.7.2")
      ```
    </Tab>

    <Tab title="Gradle">
      ```groovy theme={null}
      // https://mvnrepository.com/artifact/com.clickhouse/clickhouse-http-client
      implementation 'com.clickhouse:clickhouse-http-client:0.7.2'
      ```
    </Tab>
  </Tabs>

  自版本 `0.5.0` 起，驱动程序引入了新的客户端 HTTP 库，需将其作为依赖项添加。

  <Tabs>
    <Tab title="Maven">
      ```xml theme={null}
      <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5 -->
      <dependency>
          <groupId>org.apache.httpcomponents.client5</groupId>
          <artifactId>httpclient5</artifactId>
          <version>5.3.1</version>
      </dependency>
      ```
    </Tab>

    <Tab title="Gradle (Kotlin)">
      ```kotlin theme={null}
      // https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5
      implementation("org.apache.httpcomponents.client5:httpclient5:5.3.1")
      ```
    </Tab>

    <Tab title="Gradle">
      ```groovy theme={null}
      // https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5
      implementation 'org.apache.httpcomponents.client5:httpclient5:5.3.1'
      ```
    </Tab>
  </Tabs>

  ## 初始化

  连接 URL 格式：`protocol://host[:port][/database][?param[=value][&param[=value]][#tag[,tag]]`，例如：

  * `http://localhost:8443?ssl=true&sslmode=NONE`
  * `https://(https://explorer@play.clickhouse.com:443`

  连接到单个节点：

  ```java showLineNumbers theme={null}
  ClickHouseNode server = ClickHouseNode.of("http://localhost:8123/default?compress=0");
  ```

  连接到包含多个节点的集群：

  ```java showLineNumbers theme={null}
  ClickHouseNodes servers = ClickHouseNodes.of(
      "jdbc:ch:http://server1.domain,server2.domain,server3.domain/my_db"
      + "?load_balancing_policy=random&health_check_interval=5000&failover=2");
  ```

  ## 查询 API

  ```java showLineNumbers theme={null}
  try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.HTTP);
       ClickHouseResponse response = client.read(servers)
          .format(ClickHouseFormat.RowBinaryWithNamesAndTypes)
          .query("select * from numbers limit :limit")
          .params(1000)
          .executeAndWait()) {
              ClickHouseResponseSummary summary = response.getSummary();
              long totalRows = summary.getTotalRowsToRead();
  }
  ```

  ## 流式查询 API

  ```java showLineNumbers theme={null}
  try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.HTTP);
       ClickHouseResponse response = client.read(servers)
          .format(ClickHouseFormat.RowBinaryWithNamesAndTypes)
          .query("select * from numbers limit :limit")
          .params(1000)
          .executeAndWait()) {
              for (ClickHouseRecord r : response.records()) {
              int num = r.getValue(0).asInteger();
              // 类型转换
              String str = r.getValue(0).asString();
              LocalDate date = r.getValue(0).asDate();
          }
  }
  ```

  请参阅[代码库](https://github.com/ClickHouse/clickhouse-java/tree/main/examples/client)中的[完整代码示例](https://github.com/ClickHouse/clickhouse-java/blob/main/examples/client/src/main/java/com/clickhouse/examples/jdbc/Main.java#L73)。

  ## 插入 API

  ```java showLineNumbers theme={null}
  try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.HTTP);
       ClickHouseResponse response = client.read(servers).write()
          .format(ClickHouseFormat.RowBinaryWithNamesAndTypes)
          .query("insert into my_table select c2, c3 from input('c1 UInt8, c2 String, c3 Int32')")
          .data(myInputStream) // `myInputStream` 是 RowBinary 格式的数据源
          .executeAndWait()) {
              ClickHouseResponseSummary summary = response.getSummary();
              summary.getWrittenRows();
  }
  ```

  请参阅[代码库](https://github.com/ClickHouse/clickhouse-java/tree/main/examples/client)中的[完整代码示例](https://github.com/ClickHouse/clickhouse-java/blob/main/examples/client/src/main/java/com/clickhouse/examples/jdbc/Main.java#L39)。

  **RowBinary 编码**

  RowBinary 格式详见其[页面](/zh/reference/formats/RowBinary/RowBinaryWithNamesAndTypes)。

  这里有一个[代码示例](https://github.com/ClickHouse/clickhouse-kafka-connect/blob/main/src/main/java/com/clickhouse/kafka/connect/sink/db/ClickHouseWriter.java#L622)。

  ## 功能特性

  ### 压缩

  客户端默认使用 LZ4 压缩，需要以下依赖项：

  <Tabs>
    <Tab title="Maven">
      ```xml theme={null}
      <!-- https://mvnrepository.com/artifact/org.lz4/lz4-java -->
      <dependency>
          <groupId>org.lz4</groupId>
          <artifactId>lz4-java</artifactId>
          <version>1.8.0</version>
      </dependency>
      ```
    </Tab>

    <Tab title="Gradle (Kotlin)">
      ```kotlin theme={null}
      // https://mvnrepository.com/artifact/org.lz4/lz4-java
      implementation("org.lz4:lz4-java:1.8.0")
      ```
    </Tab>

    <Tab title="Gradle">
      ```groovy theme={null}
      // https://mvnrepository.com/artifact/org.lz4/lz4-java
      implementation 'org.lz4:lz4-java:1.8.0'
      ```
    </Tab>
  </Tabs>

  您也可以通过在连接 URL 中设置 `compress_algorithm=gzip` 来改用 gzip。

  或者，您也可以通过以下几种方式禁用压缩。

  1. 在 connection URL 中将 `compress=0` 设为禁用：`http://localhost:8123/default?compress=0`
  2. 在客户端配置中禁用：

  ```java showLineNumbers theme={null}
  ClickHouseClient client = ClickHouseClient.builder()
     .config(new ClickHouseConfig(Map.of(ClickHouseClientOption.COMPRESS, false)))
     .nodeSelector(ClickHouseNodeSelector.of(ClickHouseProtocol.HTTP))
     .build();
  ```

  请参阅[压缩文档](/zh/guides/clickhouse/data-modelling/compression/compression-modes)，了解各种压缩选项的详细信息。

  ### 多个查询

  在同一会话中，在工作线程内依次执行多个查询：

  ```java showLineNumbers theme={null}
  CompletableFuture<List<ClickHouseResponseSummary>> future = ClickHouseClient.send(servers.apply(servers.getNodeSelector()),
      "create database if not exists my_base",
      "use my_base",
      "create table if not exists test_table(s String) engine=Memory",
      "insert into test_table values('1')('2')('3')",
      "select * from test_table limit 1",
      "truncate table test_table",
      "drop table if exists test_table");
  List<ClickHouseResponseSummary> results = future.get();
  ```

  ### 命名参数

  您可以按名称传递参数，而无需依赖其在参数列表中的位置。此功能可通过 `params` 函数实现。

  ```java showLineNumbers theme={null}
  try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.HTTP);
       ClickHouseResponse response = client.read(servers)
          .format(ClickHouseFormat.RowBinaryWithNamesAndTypes)
          .query("select * from my_table where name=:name limit :limit")
          .params("Ben", 1000)
          .executeAndWait()) {
              //...
          }
  }
  ```

  <Info>
    **参数**

    所有涉及 `String` 类型 (`String`、`String[]`、`Map<String, String>`) 的 `params` 签名都默认传入的键是有效的 ClickHouse SQL 字符串。例如：

    ```java showLineNumbers theme={null}
    try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.HTTP);
         ClickHouseResponse response = client.read(servers)
            .format(ClickHouseFormat.RowBinaryWithNamesAndTypes)
            .query("select * from my_table where name=:name")
            .params(Map.of("name","'Ben'"))
            .executeAndWait()) {
                //...
            }
    }
    ```

    如果你不想手动将 String 对象转换为 ClickHouse SQL 表达式，可以使用位于 `com.clickhouse.data` 中的辅助函数 `ClickHouseValues.convertToSqlExpression`：

    ```java showLineNumbers theme={null}
    try (ClickHouseClient client = ClickHouseClient.newInstance(ClickHouseProtocol.HTTP);
         ClickHouseResponse response = client.read(servers)
            .format(ClickHouseFormat.RowBinaryWithNamesAndTypes)
            .query("select * from my_table where name=:name")
            .params(Map.of("name", ClickHouseValues.convertToSqlExpression("Ben's")))
            .executeAndWait()) {
                //...
            }
    }
    ```

    在上面的示例中，`ClickHouseValues.convertToSqlExpression` 会对内部的单引号进行转义，并用有效的单引号将变量包裹起来。

    其他类型 (如 `Integer`、`UUID`、`Array` 和 `Enum`) 会在 `params` 中自动完成转换。
  </Info>

  ## 节点发现

  Java client 提供了自动发现 ClickHouse 节点的功能。自动发现默认处于禁用状态。如需手动启用，请将 `auto_discovery` 设置为 `true`：

  ```java theme={null}
  properties.setProperty("auto_discovery", "true");
  ```

  或在连接 URL 中：

  ```plaintext theme={null}
  jdbc:ch://my-server/system?auto_discovery=true
  ```

  如果启用了自动发现功能，则无需在连接 URL 中指定所有 ClickHouse 节点。URL 中指定的节点将被视为种子节点，Java 客户端将自动从系统表和/或 clickhouse-keeper 或 zookeeper 中发现更多节点。

  以下选项用于配置自动发现功能：

  | 属性                        | 默认值     | 描述                                                 |
  | ------------------------- | ------- | -------------------------------------------------- |
  | auto\_discovery           | `false` | 客户端是否应通过系统表和/或 clickhouse-keeper/zookeeper 发现更多节点。 |
  | node\_discovery\_interval | `0`     | 节点发现间隔 (毫秒) ；值为零或负数表示仅发现一次。                        |
  | node\_discovery\_limit    | `100`   | 一次最多可发现的节点数；值为零或负数表示不受限制。                          |

  ### 负载均衡

  Java 客户端根据负载均衡策略选择 ClickHouse 节点来发送请求。通常，负载均衡策略负责以下事项：

  1. 从托管节点列表中获取节点。
  2. 管理节点状态。
  3. 可选择为节点发现调度一个后台进程 (如果已启用自动发现) ，并执行健康检查。

  以下是配置负载均衡的选项列表：

  | 配置项                     | 默认值                                      | 说明                                                                                                                                                                                                                                          |
  | ----------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | load\_balancing\_policy | `""`                                     | 负载均衡策略可以是以下之一： <li>`firstAlive` - 请求会发送到托管节点列表中的第一个健康节点</li><li>`random` - 请求会发送到托管节点列表中的任意一个节点 </li><li>`roundRobin` - 请求会依次发送到托管节点列表中的各个节点。</li><li>实现 `ClickHouseLoadBalancingPolicy` 的完全限定类名 - 自定义负载均衡策略</li>如果未指定，则请求会发送到托管节点列表中的第一个节点 |
  | load\_balancing\_tags   | `""`                                     | 用于筛选节点的负载均衡标签。请求只会发送到带有指定标签的节点                                                                                                                                                                                                              |
  | health\_check\_interval | `0`                                      | 健康检查间隔，单位为毫秒；零值或负值表示一次性。                                                                                                                                                                                                                    |
  | health\_check\_method   | `ClickHouseHealthCheckMethod.SELECT_ONE` | 健康检查方法。可以是以下任一项： <li>`ClickHouseHealthCheckMethod.SELECT_ONE` - 使用 `select 1` 查询进行检查</li> <li>`ClickHouseHealthCheckMethod.PING` - 协议专用检查，通常更快</li>                                                                                         |
  | node\_check\_interval   | `0`                                      | 节点检查间隔 (以毫秒为单位) ，负数按零处理。如果距离上次检查已超过指定时间，则会检查节点状态。<br />`health_check_interval` 与 `node_check_interval` 的区别在于，`health_check_interval` 选项会调度后台任务，用于检查节点列表 (全部节点或故障节点) 的状态，而 `node_check_interval` 则指定某个特定节点距离上次检查需要经过的时间                      |
  | check\_all\_nodes       | `false`                                  | 是否对所有节点执行健康检查，还是仅对故障节点执行健康检查。                                                                                                                                                                                                               |

  ### 故障转移与重试

  Java client 提供了配置选项，用于为失败查询设置故障转移和重试行为：

  | 属性                        | 默认值    | 说明                                                                                                                      |
  | ------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------- |
  | 故障转移                      | `0`    | 单个请求允许发生故障转移的最大次数。值为 0 或负数表示不进行故障转移。发生故障转移时，会根据负载均衡策略将失败的请求发送到其他节点，以从故障中恢复。                                             |
  | 重试                        | `0`    | 请求可重试的最大次数。零或负值表示不重试。只有在 ClickHouse server 返回 `NETWORK_ERROR` 错误码时，重试才会将请求发送到同一节点                                       |
  | repeat\_on\_session\_lock | `true` | 当会话被锁定时，是否持续重试执行直到超时 (根据 `session_timeout` 或 `connect_timeout`) 。如果 ClickHouse 服务器返回 `SESSION_IS_LOCKED` 错误代码，则会重试失败的请求 |

  ### 添加自定义 HTTP 请求头

  Java client 支持 HTTP/S 传输层，可用于向请求中添加自定义 HTTP 请求头。
  请使用 custom\_http\_headers 属性，多个请求头之间以 `,` 分隔，请求头的键/值之间以 `=` 分隔。

  ## Java Client 支持

  ```java theme={null}
  options.put("custom_http_headers", "X-ClickHouse-Quota=test, X-ClickHouse-Test=test");
  ```

  ## JDBC 驱动

  ```java theme={null}
  properties.setProperty("custom_http_headers", "X-ClickHouse-Quota=test, X-ClickHouse-Test=test");
  ```
</View>
