You need to enable JavaScript to run this app.
导航
ByteHouse JDBC Driver
最近更新时间:2025.10.22 19:18:52首次发布时间:2022.05.09 10:22:34
复制全文
我的收藏
有用
有用
无用
无用

ByteHouse JDBC Driver 是用于 Java 应用通过 JDBC 接口连接 ByteHouse 云数仓的驱动程序,支持数据查询、写入等操作,可帮助 Java 开发者快速集成 ByteHouse,实现高效的数据访问。本文介绍如何通过 JDBC 方式连接并访问 ByteHouse 云数仓。

环境要求

支持 Java 1.8.0_261 或更高版本 (需要 TLS v1.3 支持)。

推荐版本

推荐使用 ByteHouse JDBC Driver 最新版本。您可前往 ByteHouse Java Driver index 页面,获取 ByteHouse JDBC Driver 最新版本的 jar 文件。

驱动兼容性

部分 SQL/ Function 受驱动版本影响,详情参阅下表。

SQL/Function

驱动版本

replace into

≥1.1.67

安装驱动

本地安装

请单击前往 ByteHouse Java Driver index 页面,获取 ByteHouse JDBC Driver 最新版本的 jar 文件。
获取 jar 文件后,您只需将编译后的 jar 文件添加到您的项目中,或者使用您选择的依赖项管理工具将此项目添加为依赖项。然后,您可以导入并使用 Java 程序中的类。

添加为 Gradle 依赖

通过 Gradle 方式使用 ByteHouse JDBC 驱动的示例如下:

repositories {
    // This is public bytedance repository for downloading artifacts 
    maven {
        url "https://artifact.bytedance.com/repository/releases"
    }
}

dependencies {
    implementation "com.bytedance.bytehouse:driver-java:1.1.74:all"
}

说明

以上示例中,java:1.1.74为一个示例的版本号,实际使用时,您需替换为最新的版本号。前往 ByteHouse Java Driver index 页面获取最新版本的驱动文件。

添加为 Maven 依赖

通过 Maven 方式使用 ByteHouse JDBC 驱动的示例如下:

// This is public bytedance repository for downloading artifacts 
<repository>
    <id>bytedance</id>
    <name>ByteDance Public Repository</name>
    <url>https://artifact.bytedance.com/repository/releases</url>
</repository>

<dependency>
    <groupId>com.bytedance.bytehouse</groupId>
    <artifactId>driver-java</artifactId>
    <version>1.1.74</version>
    <classifier>all</classifier>
</dependency> 

说明

以上示例中,java:1.1.74为一个示例的版本号,实际使用时,您需替换为最新的版本号。前往 ByteHouse Java Driver index 页面获取最新版本的驱动文件。

获取 ByteHouse 连接信息

ByteHouse 支持通过 IAM 用户或数据库用户连接 ByteHouse JDBC Driver。IAM 用户与数据库用户二者差异说明如下,您可按需选择。

  • IAM 用户为火山引擎访问控制(IAM)中创建的用户,其权限由 IAM 权限策略及您授予的 ByteHouse 资源和数据权限决定。IAM 用户可访问 ByteHouse 控制台,也支持通过 CLI、连接驱动、生态工具、API 等方式访问 ByteHouse。
  • 数据库用户为 ByteHouse 中创建的数据库级别用户,可为其授予环境、资源和数据权限。数据库用户不可访问 ByteHouse 控制台,但支持通过 CLI、连接驱动、生态工具、API 等方式访问 ByteHouse。

更多 IAM 用户和数据库用户的介绍请参见以下文档:

IAM 用户

请参考步骤三:获取 ByteHouse 连接串信息,了解如何通过 IAM 用户方式连接到 ByteHouse。
通用参数说明如下:

参数

配置说明

Host

配置为 ByteHouse 的公网/私网域名,您可以在 ByteHouse 控制台的租户管理 > 基本信息 > 网络信息中查看并复制域名信息,详情请参见步骤二:配置网络信息

Port

固定为 19000。

User

固定为 bytehouse。

Password

为 ByteHouse 的 API Key,您可以在 ByteHouse 控制台的租户管理 > 连接信息中获取 API Key,详情请参见获取 API Key

Database

配置为连接 ByteHouse 数据库名称。您可登录 ByteHouse控制台,在数据库页面查看并复制数据库。

virtual_warehouse

可选配置,配置为计算组名。如果您需要指定计算组进行查询和写入,可配置该参数。
您可登录 ByteHouse 控制台,单击顶部计算组,查看并复制计算组 ID。示例:vw-{environment_id}{account_id}-{virtual_warehouse_name}
如果不配置,则默认使用您在 ByteHouse 设置的默认计算组。

数据库用户

请参考步骤三:获取 ByteHouse 连接串信息,了解如何通过数据库用户的方式连接到 ByteHouse。
通用参数说明如下:

参数

配置说明

Host

配置为 ByteHouse 的公网/私网域名,您可以在 ByteHouse 控制台的租户管理 > 基本信息 > 网络信息中查看并复制域名信息,详情请参见步骤二:配置网络信息

Port

固定为 19000。

User

username 配置为 {accountID_or_accountName}::{username}[::{envID}],详情请参见获取数据库用户及密码

  • {accountID_or_accountName} :指火山引擎用户账号 ID 或名称,可登录 ByteHouse 控制台,单击右上角个人中心查看并复制账号 ID 或名称。

  • {username} :指登录 ByteHouse 数据库账号的用户名。可在ByteHouse 控制台 > 权限管理 > 用户 > 查看数据库用户名

  • {envID}:可选配置,数据库所在的环境名称。如果使用 default 环境,可不配置;如需使用其他环境,需指定环境名称,配置时无需添加[]。您可登录 ByteHouse 控制台,在租户管理 > 基本信息 > 当前环境中获取。

    使用示例如下:

    • 配置环境 ID:21xxxxxxxx::demouser::demoenv
    • 不配置环境 ID:21xxxxxxxx::demouser

Password

数据库账号的密码由管理员创建数据库账号时自定义配置,您可联系管理员获取密码。如果密码丢失或遗忘,可通联系管理员重置密码,详情请参考重置密码

Database

配置为连接 ByteHouse 数据库名称。您可登录 ByteHouse控制台,在数据库页面查看并复制数据库。

virtual_warehouse

可选配置,配置为计算组名。如果您需要指定计算组进行查询和写入,可配置该参数。
您可登录 ByteHouse 控制台,单击顶部计算组,查看并复制计算组 ID。示例:vw-{environment_id}{account_id}-{virtual_warehouse_name}
如果不配置,则默认使用您在 ByteHouse 设置的默认计算组。

基本用法

您可以使用以下代码连接至 ByteHouse,并开始使用标准语句开发 ByteHouse,用于查询、写入和读取数据。

  • 超时时间配置:ping_timeout 默认为 10s、query_timeout 默认为 0s、connect_timeout 默认为 0s,send_timeout 和 receive_timeout 当前暂不生效。
  • 默认支持 keepAlive,可以复用连接和避免短链接。

连接 ByteHouse

可参考下面代码连接至 ByteHouse,使用时注意替换连接语句中的 {host}{Password}{User}{Database}{VITUAL_WAREHOUSE_ID} 等连接信息字段,获取方式请参见获取 ByteHouse 连接信息

使用 Propertities 配置连接

import com.bytedance.bytehouse.jdbc.statement.ByteHouseStatement;

import java.sql.*;
import java.util.Properties;
import java.util.UUID;

public class BHJDBC {
    public static void main(String[] args) {
        String host = "{Host}";
        int port = 19000;
        String password = "{Password}";
        String user = "{User}";
        String database = "{Database}";
        String virtual_warehouse_id = "{VIRTUAL_WAREHOUSE_ID}";

        // 通过 properties 设置一些链接的基本参数
        String url = String.format("jdbc:bytehouse://%s:%d", host, port);
        Properties properties = new Properties();
        // 可以按需设置不同的计算组
          properties.setProperty("virtual_warehouse", virtual_warehouse_id);
          properties.setProperty("secure", "true");
          properties.setProperty("user", user);
          properties.setProperty("password", password);
          properties.setProperty("database", database);

        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url, properties);
        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

使用 URL 的 param 配置连接

import com.bytedance.bytehouse.jdbc.statement.ByteHouseStatement;

import java.sql.*;
import java.util.Properties;
import java.util.UUID;

public class BHJDBC {
    public static void main(String[] args) {
        String host = "{Host}";
        int port = 19000;
        String password = "{Password}";
        String user = "{User}";
        String database = "{Database}";
        String virtual_warehouse_id = "{VIRTUAL_WAREHOUSE_ID}";

        String url = String.format("jdbc:bytehouse://%s:%d/?secure=true&user=%s&password=%s&database=%s&virtual_warehouse=%s",
                host, port, user, password, database, virtual_warehouse_id);


        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url);
        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

创建数据库、表

与 ByteHouse 建立连接后,您可以使用以下代码创建数据库、表。

public static void dropDatabase(Connection connection) {
        Statement stmt = null;
        try {
            stmt = connection.createStatement();
            String dropDbQuery = "Drop DATABASE IF EXISTS bhjdbctest";
            stmt.execute(dropDbQuery);
        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (stmt != null) stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
     /*
     * 创建数据库
     */
    public static void createDatabase(Connection connection) {
        Statement stmt = null;
        try {
            stmt = connection.createStatement();
            String createDbQuery = "CREATE DATABASE IF NOT EXISTS bhjdbctest";
            stmt.execute(createDbQuery);
        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (stmt != null) stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
     /*
     * 创建表
     */
    public static void createTable(Connection connection) {
        Statement stmt = null;
        try {
            stmt = connection.createStatement();
            String createTableQuery = "CREATE TABLE IF NOT EXISTS bhjdbctest.orders\n (" +
                    "OrderID String, OrderName String, OrderPriority Int8)" +
                    " engine = CnchMergeTree() partition by OrderID order by OrderID";
            stmt.execute(createTableQuery);
        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (stmt != null) stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

写入数据

您可以使用以下代码写入数据。

/*
     * 插入数据
     */
    public static void insertTable(Connection connection) {
        Statement stmt = null;
        try {
            stmt = connection.createStatement();
            String insertQuery = "INSERT INTO bhjdbctest.orders VALUES ('54895','Apple',12)";
            stmt.executeUpdate(insertQuery);
        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (stmt != null) stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
     /*
     * 批量插入数据
     */
    public static void insertBatch(Connection connection) {
        PreparedStatement pstmt = null;
        String insertQuery = "INSERT INTO bhjdbctest.orders (OrderID, OrderName, OrderPriority) VALUES (?,'Apple',?)";
        try {
            pstmt = connection.prepareStatement(insertQuery);
            int insertBatchSize = 10;
            for (int i = 0; i < insertBatchSize; i++) {
                pstmt.setString(1, "ID" + i);
                pstmt.setInt(2, i);
                pstmt.addBatch();
            }
            pstmt.executeBatch();

        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (pstmt != null) pstmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

查询

您可以使用以下代码查询数据。

/*
     * 查询数据
     */
    public static void selectTable(Connection connection) {
        Statement stmt = null;
        try {
            stmt = connection.createStatement();
            String selectTableQuery = "SELECT * FROM bhjdbctest.orders";
            ResultSet rs = stmt.executeQuery(selectTableQuery);
            ResultSetMetaData rsmd = rs.getMetaData();
            int columnsNumber = rsmd.getColumnCount();
            while (rs.next()) {
                for (int i = 1; i <= columnsNumber; i++) {
                    if (i > 1) System.out.print(", ");
                    String columnValue = rs.getString(i);
                    System.out.print(columnValue);
                }
                System.out.println();
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (stmt != null) stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

使用 Query ID

设置 query ID 有助于追踪查询执行情况,方便后续调试或管理查询任务。您可以使用 JDBC 原生方式,也可以使用 ByteHouse 专用接口,为查询语句设置 query ID。

自定义 query ID

如果您需要为某条查询语句设置 query ID,可参考以下代码,添加 stmt.setQueryId(String.format("customized_%s", UUID.randomUUID())); 代码。

public static void dropDatabaseWithQueryId(Connection connection) {
        ByteHouseStatement stmt = null;
        try {
            stmt = (ByteHouseStatement)connection.createStatement();
            stmt.setQueryId(String.format("customized_%s", UUID.randomUUID()));
            String createDbQuery = "Drop DATABASE IF EXISTS bhjdbctest";
            stmt.execute(createDbQuery);
        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (stmt != null) stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

使用 ByteHouse 专用接口

ByteHouse JDBC 驱动从 v1.1.83 版本起支持了为查询分配自定义 Query ID 功能。

前提条件

使用 Query ID 功能前,请确保满足以下条件:

  • ByteHouse JDBC Driver 版本为 v1.1.83 及以上。
  • 将 JDBC 接口替换为 ByteHouse 专用接口:
    • ConnectionByteHouseConnection
    • StatementByteHouseStatement
    • PreparedStatementByteHousePreparedStatement

如果使用时未明确指定 Query ID,ByteHouse JDBC 驱动将随机自动生成 Query ID,并将其与查询关联。

API 概览

API 接口

配置说明

ByteHouseConnection.setQueryId(String queryId)

仅为下一条查询设置 Query ID。

((ByteHouseConnection) connection).setQueryId("next-query-id");
connection.createStatement().executeQuery("SELECT 1");
// Query ID: "next-query-id"

ByteHouseStatement.setQueryId(String queryId)

将 Query ID 直接设置到 ByteHouseStatement 中。

ByteHouseStatement statement = (ByteHouseStatement) connection.createStatement();
statement.setQueryId("next-query-id");
statement.executeQuery("SELECT 1");
// Query ID: "next-query-id"

ByteHousePreparedStatement.setQueryId(String queryId)

JDBC 与 ByteHouse 交互的方式所限,Query ID 必须在 PreparedStatement 创建前设置。因此请勿在 PreparedStatement 上直接使用 setQueryId() 插入数据。正确示例如下:

((ByteHouseConnection) connection).setQueryId("first-query-id");
ByteHousePreparedInsertStatement ps = (ByteHousePreparedInsertStatement) connection.prepareStatement("INSERT INTO demo.tbl VALUES (?)");
ps.setObject(1, 1);
ps.execute();
// Query ID: "first-query-id"

// 为下一次查询设置新的 query ID
((ByteHouseConnection) connection).setQueryId("second-query-id");
ps.setObject(1, 2);
ps.execute();
// Query ID: "second-query-id"

ByteHouseConnection.getQueryId()

返回连接后的最后一个 Query ID。

((ByteHouseConnection) connection).setQueryId("first-query-id");
assertEquals(((ByteHouseConnection) connection).getQueryId(), "first-query-id");

ByteHousePreparedInsertStatement ps = (ByteHousePreparedInsertStatement) connection.prepareStatement("INSERT INTO demo.tbl VALUES (?)");
ps.setObject(1, 1);
ps.execute();
assertEquals(((ByteHouseConnection) connection).getQueryId(), "first-query-id");

使用会话级 Query ID 前缀

您可以使用 session_query_id_prefix 属性为所有 Query ID 设置会话级的前缀。

Properties props = new Properties();
props.setProperty("session_query_id_prefix", "my-spark-application-");

Connection connection = new ByteHouseDriver().connect(jdbcUrl, props);

示例 1:仅前缀(无显式 Query ID)

JDBC会自动为每个查询的前缀添加一个递增的计数器:

Properties props = new Properties();
props.setProperty("session_query_id_prefix", "my-spark-application-");

Connection connection = new ByteHouseDriver().connect(jdbcUrl, props);

connection.createStatement().executeQuery("DROP DATABASE IF EXISTS demo"); 
// Query ID: "my-spark-application-1"
connection.createStatement().executeQuery("CREATE DATABASE IF NOT EXISTS demo");
// Query ID: "my-spark-application-2"
connection.createStatement().executeQuery("CREATE TABLE demo.tbl(id INT) ENGINE=CnchMergeTree ORDER BY id");
// Query ID: "my-spark-application-3"

示例 2:前缀 + 显式 Query ID

驱动程序将前缀与用户指定的查询ID连接起来。不自动递增。

Properties props = new Properties();
props.setProperty("session_query_id_prefix", "my-spark-application-");

Connection connection = new ByteHouseDriver().connect(jdbcUrl, props);

((ByteHouseConnection) connection).setQueryId("drop-db");
connection.createStatement().executeQuery("DROP DATABASE IF EXISTS demo");
// Query ID: "my-spark-application-drop-db"
((ByteHouseConnection) connection).setQueryId("create-db");
connection.createStatement().executeQuery("CREATE DATABASE IF NOT EXISTS demo");
// Query ID: "my-spark-application-create-db"

配置连接池

ByteHouse 支持通过 HikariCP 和 Druid 进行 JDBC 连接和数据开发。

通过 HikariCP 进行 JDBC 连接

下面举例介绍如何通过 ByteHouse JDBC 驱动程序与 HikariCP 连接。

Maven 依赖

通过 Maven 方式使用 ByteHouse JDBC 驱动时,请在 pom.xml 文件中添加以下依赖项以包含 HikariCP:

<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>4.0.3</version>
</dependency>

Gradle 依赖

通过 Gradle 方式使用 ByteHouse JDBC 驱动时,请在 build.gradle 文件中添加以下依赖项以包含 HikariCP:

dependencies {
    implementation 'com.zaxxer:HikariCP:4.0.3'
} 

类名

使用 HikariCP 时,您最常与之交互的类是 HikariDataSource。您可以按照以下示例在 Java 应用程序中配置和使用 HikariCP 来创建 Bytehouse 连接。

连接与查询

可参考下面代码连接至 ByteHouse,使用时注意替换连接语句中的hostportpassworduserdatabasevirtual_warehouse_id 等连接信息字段,获取方式请参见获取 ByteHouse 连接信息

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.sql.*;

public class HikariConnection {
    public static Connection getConnectionWithHikariConfig(String host, String port, String apiKey) throws Exception {

        HikariConfig config = new HikariConfig();
        String jdbcURL = String.format("jdbc:bytehouse://%s:%s/?api_key=%s", host, port, apiKey);
        
        // 标准 Hikari 配置
        config.setJdbcUrl(jdbcURL);
        config.setMinimumIdle(5); // 池中的最小空闲连接数
        config.setMaximumPoolSize(20); // 池中的最大连接数
        config.setMaxLifetime(4 * 60 * 1000); // 连接将在 4 分钟后失效(被回收),最长允许(的存活时间)为 5 分钟
        config.setIdleTimeout(2 * 60 * 1000); // 连接闲置 2 分钟后,即符合被驱逐(回收)的条件

        config.setPoolName("BH-Pool");
        config.addDataSourceProperty("secure", "true");
        // config.addDataSourceProperty("virtual_warehouse", {VIRTUAL_WAREHOUSE_ID});

        HikariDataSource hds = new HikariDataSource(config);
        Connection conn = hds.getConnection();
        return conn;
    }

    public static void main(String[] args) {
        String host = "{HOST}";
        String apiKey = "{API_KEY}";
        String port = "19000"; 
        try {
            Connection connection = getConnectionWithHikariConfig(host, port, apiKey);
            createDatabase(connection);
            createTable(connection);
            insertTable(connection);
            insertBatch(connection);
            selectTable(connection);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void createDatabase(Connection connection) {
        try (Statement stmt = connection.createStatement()) {
            String createDbQuery = "CREATE DATABASE IF NOT EXISTS inventory";
            stmt.execute(createDbQuery);
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

    public static void createTable(Connection connection) {
        try (Statement stmt = connection.createStatement()) {

            String createTableQuery = "CREATE TABLE IF NOT EXISTS inventory.orders\n (" +
                    "OrderID String, OrderName String, OrderPriority Int8)" +
                    " engine = CnchMergeTree() partition by OrderID order by OrderID";
            stmt.execute(
                    createTableQuery
            );
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

    public static void insertTable(Connection connection) {
        try (Statement stmt = connection.createStatement()) {
            String insertQuery = "INSERT INTO inventory.orders VALUES ('54895','Apple',12)";
            stmt.executeUpdate(
                    insertQuery
            );
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

    public static void insertBatch(Connection connection) {
        String insertQuery = "INSERT INTO inventory.orders (OrderID, OrderName, OrderPriority) VALUES (?,'Apple',?)";
        try (PreparedStatement pstmt = connection.prepareStatement(insertQuery)) {
            int insertBatchSize = 10;

            for (int i = 0; i < insertBatchSize; i++) {
                pstmt.setString(1, "ID" + i);
                pstmt.setInt(2, i);
                pstmt.addBatch();
            }
            pstmt.executeBatch();

        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

    public static void selectTable(Connection connection) {
        try (Statement stmt = connection.createStatement()) {
            String selectTableQuery = "SELECT * FROM inventory.orders";
            ResultSet rs = stmt.executeQuery(selectTableQuery);
            ResultSetMetaData rsmd = rs.getMetaData();
            int columnsNumber = rsmd.getColumnCount();
            while (rs.next()) {
                for (int i = 1; i <= columnsNumber; i++) {
                    if (i > 1) System.out.print(", ");
                    String columnValue = rs.getString(i);
                    System.out.print(columnValue);
                }
                System.out.println();
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }
}

通过 Druid 进行 JDBC 连接

您也可以通过阿里巴巴的 Druid 连接池来连接 ByteHouse。

Maven 依赖

通过 Maven 方式使用 ByteHouse JDBC 驱动时,请在 pom.xml 文件中添加以下依赖项以包含 Druid:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.23</version>
</dependency>

Gradle 依赖

通过 Gradle 方式使用 ByteHouse JDBC 驱动时,请在 build.gradle 文件中添加以下依赖项以包含 Druid:

dependencies {
     implementation 'com.alibaba:druid:1.1.23' 
}

类名

在使用 Druid 时,您最常与之交互的类是 DruidDataSource。您可以按照以下示例在Java 应用程序中配置和使用 Druid 来创建 Bytehouse 连接。

连接与查询

可参考下面连接至 ByteHouse,使用时注意替换连接语句中的hostportpassworduserdatabasevirtual_warehouse_id 等连接信息字段,获取方式请参见获取 ByteHouse 连接信息

import com.alibaba.druid.pool.DruidDataSource;
import java.sql.*;
import java.util.Properties;

public class DruidConnection {
    public static Connection getConnectionWithDruidConfig(String host, String port, String apiKey) throws Exception {

        DruidDataSource druidDataSource = new DruidDataSource();
        String jdbcURL = String.format("jdbc:bytehouse://%s:%s/?api_key=%s", host, port, apiKey);
        druidDataSource.setUrl(jdbcURL);
        druidDataSource.setDriverClassName("com.bytedance.bytehouse.jdbc.ByteHouseDriver");
        druidDataSource.setMaxActive(10); // 最大活跃连接数
        druidDataSource.setInitialSize(2); // 初始连接数
        druidDataSource.setMinIdle(2); // 最小空闲连接数
        druidDataSource.setMaxWait(50000); // 获取连接的最大等待时间
        Properties properties = druidDataSource.getConnectProperties();
        properties.setProperty("secure", "true");
        // properties.setProperty("virtual_warehouse", {VIRTUAL_WAREHOUSE_ID});

        druidDataSource.setConnectProperties(properties);
        Connection conn = druidDataSource.getConnection();

        return conn;
    }

    public static void main(String[] args) {
        String host = "{HOST}";
        String apiKey = "{API_KEY}";
        String port = "19000"; 
        try {
            Connection connection = getConnectionWithDruidConfig(host, port, apiKey);
            createDatabase(connection);
            createTable(connection);
            insertTable(connection);
            insertBatch(connection);
            selectTable(connection);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void createDatabase(Connection connection) {
        try (Statement stmt = connection.createStatement()) {
            String createDbQuery = "CREATE DATABASE IF NOT EXISTS inventory";
            stmt.execute(createDbQuery);
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

    public static void createTable(Connection connection) {
        try (Statement stmt = connection.createStatement()) {

            String createTableQuery = "CREATE TABLE IF NOT EXISTS inventory.orders\n (" +
                    "OrderID String, OrderName String, OrderPriority Int8)" +
                    " engine = CnchMergeTree() partition by OrderID order by OrderID";
            stmt.execute(
                    createTableQuery
            );
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

    public static void insertTable(Connection connection) {
        try (Statement stmt = connection.createStatement()) {
            String insertQuery = "INSERT INTO inventory.orders VALUES ('54895','Apple',12)";
            stmt.executeUpdate(
                    insertQuery
            );
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

    public static void insertBatch(Connection connection) {
        String insertQuery = "INSERT INTO inventory.orders (OrderID, OrderName, OrderPriority) VALUES (?,'Apple',?)";
        try (PreparedStatement pstmt = connection.prepareStatement(insertQuery)) {
            int insertBatchSize = 10;

            for (int i = 0; i < insertBatchSize; i++) {
                pstmt.setString(1, "ID" + i);
                pstmt.setInt(2, i);
                pstmt.addBatch();
            }
            pstmt.executeBatch();

        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }

    public static void selectTable(Connection connection) {
        try (Statement stmt = connection.createStatement()) {
            String selectTableQuery = "SELECT * FROM inventory.orders";
            ResultSet rs = stmt.executeQuery(selectTableQuery);
            ResultSetMetaData rsmd = rs.getMetaData();
            int columnsNumber = rsmd.getColumnCount();
            while (rs.next()) {
                for (int i = 1; i <= columnsNumber; i++) {
                    if (i > 1) System.out.print(", ");
                    String columnValue = rs.getString(i);
                    System.out.print(columnValue);
                }
                System.out.println();
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }
}

常见问题

Unsupported or unrecognized SSL message 报错

如果您在使用过程中遇到 Unsupported or unrecognized SSL message 报错,这是 Java 版本过低导致的,Java 1.8.0_261 **** 以下版本会出现此报错。
您可通过以下方式解决:

  • 升级 Java 版本到 Java 11。
  • 如需保留 Java 1.8 环境,可升级至 Java 1.8.0_261 及更高补丁版本解决该问题。

DB::Exception: No local available worker group for vw-xxxx

如果您在使用过程中遇到 DB::Exception: No local available worker group for vw-xxxx 报错,这是计算组尚未启动导致的。
您可通过以下方式解决:
登录 ByteHouse 云数仓版控制台,在计算组页面,查看您使用的计算组是否在 正在运行的状态。

Code: UNAUTHENTICATED

如果您在使用过程中遇到 Exception: unknown error: Code: UNAUTHENTICATED 报错,这可能是 userpassword 配置错误导致的。
您可通过以下方式解决:
再次确认您配置的userpassword是否正确。

DB::Exception: Database xxx.yyy doesn't exist

如果您在使用过程中遇到 DB::Exception: Database xxx.yyy doesn't exist 报错,这可能是数据库名称配置错误导致的。
您可通过以下方式解决:
请确认连接信息中配置的数据库名称是否正确。

Exception: No appropriate protocol

如果您在使用过程中遇到 Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate) 报错,这可能是TLS版本不兼容导致的。
您可通过以下方式解决:
请在连接 URL 后面增加一个参数:enabledTLSProtocols=TLSv1.2,TLSv1.3
举例如下:

String url = String.format("jdbc:bytehouse://%s:%d/%s?enabledTLSProtocols=TLSv1.2,TLSv1.3", host, port, database);