You need to enable JavaScript to run this app.
ByteHouse Cloud Data Warehouse Version

ByteHouse Cloud Data Warehouse Version

Copy page
Download PDF
JDBC
ByteHouse JDBC Driver
Copy page
Download PDF
ByteHouse JDBC Driver

ByteHouse JDBC Driver is a driver that enables Java applications to connect to the ByteHouse cloud data warehouse through the JDBC interface. It supports data querying, insertion, and other operations, helping Java developers quickly integrate ByteHouse and achieve efficient data access. This article introduces how to connect to and access the ByteHouse cloud data warehouse using JDBC.

Environment requirements

Support Java 1.8.0_261 or later (requires TLS v1.3 support).

It is recommended to use the latest version of ByteHouse JDBC Driver. Go to the ByteHouse Java Driver index page to obtain the latest version of the ByteHouse JDBC Driver jar file.

Driver compatibility

Some SQL statements and functions are affected by the driver version. For details, refer to the table below.

SQL/Function

Driver version

replace into

≥1.1.67

Install drivers

Local installation

Please click to go to the ByteHouse Java Driver index page. There, you can obtain the latest version of the ByteHouse JDBC Driver jar file.
After obtaining the jar file, simply add the compiled jar file to your project, or use your chosen dependency management tool to add this project as a dependency. Then, you can import and use classes in a Java program.

Add as a Gradle dependency

The following is an example of using the ByteHouse JDBC driver with Gradle:

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"
}

tip

In the above example, java:1.1.74 is a sample version number. In practice, you need to replace it with the latest version number. Go to the ByteHouse Java Driver index page to obtain the latest version of the driver file.

Add as a Maven dependency

Examples of using the ByteHouse JDBC driver via Maven are as follows:

// 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> 

tip

In the above example, java:1.1.74 is a sample version number. When using this example, replace the sample version number with the latest version number. Go to the ByteHouse Java Driver index page to obtain the latest version of the driver file.

Obtain ByteHouse connection information

ByteHouse supports connecting to the ByteHouse JDBC Driver using IAM users or database users. The differences between IAM users and database users are described below; you may choose as needed.

  • IAM User is a user created in BytePlus Identity and Access Management (IAM). The user's permissions are determined by IAM permission policies and the ByteHouse resource and data permissions you grant. IAM users can access the ByteHouse Console, and ByteHouse also supports access through CLI, connection drivers, ecosystem tools, API, and other methods.
  • Database User is a database-level user created in ByteHouse and can be granted environment, resources, and data permissions. Database users cannot access the ByteHouse Console, but access to ByteHouse is supported through CLI, connection drivers, ecosystem tools, API, and many other methods.

For more information about IAM users and database users, refer to the following documents:

IAM users

Please refer to步骤三:获取 ByteHouse 连接串信息Learn how to connect to ByteHouse using IAM user.
General parameter description as follows

Param

Configuration description

Host

Configured as ByteHouse's public or private domain name, you can view and copy the domain name information in the ByteHouse Console under Tenant Management > Basic Information > Network Information, for details please see步骤二:配置网络信息。

Port

Fixed at 19000.

User

Fixed to bytehouse.

Password

To obtain the ByteHouse API Key, you can get it in the ByteHouse Console under Tenant Management > Connection Information. For details, see获取 API Key。

Database

Configure the ByteHouse database name for connection. You can log in to the ByteHouse Console and view and copy databases on the Database page.

virtual_warehouse

This is an optional configuration that is set to the virtual warehouse group name. To specify a virtual warehouse for query and write operations, configure this parameter.
Log in to the ByteHouse Console, click virtual warehouse at the top, and then view and copy the virtual warehouse ID. Example: vw-{environment_id}{account_id}-{virtual_warehouse_name}.
If no configuration is made, your default virtual warehouse set in ByteHouse will be used.

Database users

Please refer to步骤三:获取 ByteHouse 连接串信息Learn how to connect to ByteHouse using a database user account.
General parameter descriptions are as follows:

Param

Configuration description

Host

The domain name information configured as ByteHouse's public or private domain name can be viewed and copied in the ByteHouse Console under Tenant Management > Basic Information > Network Information. For details, see步骤二:配置网络信息。

Port

Fixed at 19000.

User

Username is configured as {accountID_or_accountName}::{username}[::{envID}]. For details, see获取数据库用户及密码:

  • {accountID_or_accountName}: This refers to the BytePlus User Account ID or Name. Log in to the ByteHouse Console, click Personal Center in the upper right corner to view and copy the Account ID or Name.
  • {username}: Refers to the username of the ByteHouse database account used to log in. You can view the database username in ByteHouse Console > Authorization > Users > View Database Username.
  • {envID}: Optional configuration, the name of the environment where the database is located. If you use the default environment, configuration is not required; to use other environments, specify the environment name, and do not add [] during configuration. You can log in to the ByteHouse Console, where you can obtain it inTenant management > Basic information > Current environment.

Usage examples are as follows:

  • Configuration environment ID: 21xxxxxxxx::demouser::demoenv
  • No environment ID configured: 21xxxxxxxx::demouser

Password

The database account password is custom-configured by the administrator when creating the account. You may contact the administrator to obtain the password. If your password is lost or forgotten, you can contact the administrator to reset it. For details, please refer to重置密码。

Database

Configure the ByteHouse database name for connection. Log in to the ByteHouse Console. On the Database page, you can view and copy databases.

virtual_warehouse

Optional configuration. Configure as the virtual warehouse name. To specify a virtual warehouse for query and write operations, configure this parameter.
Log in to the ByteHouse Console, click the virtual warehouse at the top, and view and copy the virtual warehouse ID. Example: vw-{environment_id}{account_id}-{virtual_warehouse_name}.
If no configuration is set, your default virtual warehouse set in ByteHouse will be used.

Basic usage

You can use the following code to connect to ByteHouse and start using standard statements to develop using ByteHouse for querying, writing, and reading data.

  • Timeout configuration: The default value of ping_timeout is 10s, query_timeout is 0s, and connect_timeout is 0s. The send_timeout and receive_timeout parameters do not take effect currently.
  • Default support for keepAlive enables connection reuse and avoids short-lived connections.

Connect ByteHouse

You can refer to the code below to connect to ByteHouse. When using the code below, be sure to replace the following fields in the connection statement: {host}, {Password}, {User}, {Database}, {VITUAL_WAREHOUSE_ID}, and other connection information fields. For information on how to obtain these fields, see获取 ByteHouse 连接信息。

Use Properties to configure a connection

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}";

        // Use properties to set some basic parameters of the link
        String url = String.format("jdbc:bytehouse://%s:%d", host, port);
        Properties properties = new Properties();
        // Different virtual warehouses can be set as needed
          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();
            }
        }
    }

Use a URL parameter configuration to connect

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();
            }
        }
    }

Create databases and tables

After establishing a connection with ByteHouse, you can use the following code to create a database and a table.

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();
            }
        }
    }
     /*
     * Create database
     */
    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();
            }
        }
    }
     /*
     * Create table
     */
    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();
            }
        }
    }

Write data

You can use the following code to write data.

/*
     * Insert data
     */
    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();
            }
        }
    }
     /*
     * Batch insert data
     */
    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();
            }
        }
    }

You can use the following code to query data.

/*
     * Query data
     */
    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();
            }
        }
    }
}

Use Query ID

Setting a query ID helps track query execution status and facilitates subsequent debugging or management of query tasks. You can use the native JDBC method or the ByteHouse-specific interface to set the query ID for a query.

Custom query IDs

To set the query ID for a query statement, refer to the following code and add the stmt.setQueryId(String.format("customized_%s", UUID.randomUUID())); code.

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();
            }
        }
    }

Use ByteHouse dedicated interface

Starting from version v1.1.83, the ByteHouse JDBC driver supports the feature for assigning a custom Query ID to queries.

prerequisites

Before using the Query ID feature, please ensure that the following conditions are satisfied:

  • The ByteHouse JDBC Driver version is v1.1.83 or later.
  • Replace JDBC interfaces with ByteHouse-specific interfaces:
    • Connection → ByteHouseConnection
    • Statement → ByteHouseStatement
    • PreparedStatement → ByteHousePreparedStatement

If a Query ID is not explicitly specified during use, the ByteHouse JDBC driver will randomly and automatically generate a Query ID and associate it with the query.

API Overview

API

Configuration description

ByteHouseConnection.setQueryId(String queryId)

Set the Query ID only for the next query.

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

ByteHouseStatement.setQueryId(String queryId)

Set the Query ID directly in ByteHouseStatement.

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

ByteHousePreparedStatement.setQueryId(String queryId)

Due to limitations in the interaction between JDBC and ByteHouse, the Query ID must be set before the PreparedStatement is created. Therefore, do not directly use setQueryId() on PreparedStatement to insert data. Correct samples are as follows:

((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"

// Set a new query ID for the next query
((ByteHouseConnection) connection).setQueryId("second-query-id");
ps.setObject(1, 2);
ps.execute();
// Query ID: "second-query-id"

ByteHouseConnection.getQueryId()

Return the last Query ID after connection.

((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");

Use session-level Query ID prefix

You can use the session_query_id_prefix property to set a session-level prefix for all Query IDs.

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

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

Sample 1: Prefix only (no explicit Query ID)

JDBC automatically adds an incrementing counter to each query's prefix:

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"

Example 2: Prefix + explicit Query ID

The driver program concatenates the prefix with the user-specified Query ID. Does not increment automatically.

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"

Configure connection pools

ByteHouse supports JDBC connections and data development using HikariCP and Druid.

JDBC connection through HikariCP

The following example shows how to connect to HikariCP using the ByteHouse JDBC driver.

Maven dependencies

When using the ByteHouse JDBC driver with Maven, add the following dependencies to the pom.xml file to include HikariCP:

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

Gradle dependencies

When using the ByteHouse JDBC driver with Gradle, add the following dependency to the build.gradle file to include HikariCP:

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

Class name

When you use HikariCP, the class you interact with most frequently is HikariDataSource. You can configure and use HikariCP in a Java application as shown in the following example to create a Bytehouse connection.

Connections and queries

You can refer to the code below to connect to ByteHouse. When using it, be sure to replace the connection information fields in the connection statement, such as host, port, password, user, database, virtual_warehouse_id, and more. For information on how to obtain these fields, please refer to获取 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);
        
        // Standard Hikari configuration
        config.setJdbcUrl(jdbcURL);
        config.setMinimumIdle(5); // Min number of free connections in the pool
        config.setMaximumPoolSize(20); // Max connections in the pool
        config.setMaxLifetime(4 * 60 * 1000); // The connection will expire (be reclaimed) in 4 minutes, with a maximum allowed lifetime of 5 minutes
        config.setIdleTimeout(2 * 60 * 1000); // After the connection is idle for 2 minutes, it meets the condition for eviction (recycling)

        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();
        }
    }
}

Connect to JDBC using Druid

You can also connect to ByteHouse through Alibaba's Druid connection pool.

Maven dependencies

When using the ByteHouse JDBC driver with Maven, add the following dependencies to the pom.xml file to include Druid:

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

Gradle dependencies

Please add the following dependencies to the build.gradle file to include Druid:

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

Class name

When using Druid, the class you interact with most frequently is DruidDataSource. You can configure and use Druid in a Java application to create a Bytehouse connection by following the example below.

Connections and queries

Refer to the following to connect to ByteHouse. Caution: When connecting, be sure to replace the fields in the connection statement, such as host, port, password, user, database, virtual_warehouse_id, and more. For information on how to obtain these values, see获取 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); // Max active connections
        druidDataSource.setInitialSize(2); // Initial connection count
        druidDataSource.setMinIdle(2); // Min idle connection count
        druidDataSource.setMaxWait(50000); // Max wait time for obtaining a connection
        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();
        }
    }
}

FAQs

Unsupported or unrecognized SSL message error

If you encounter the Unsupported or unrecognized SSL message error during use, it is caused by a Java version that is too low. This error occurs in Java versions below 1.8.0_261 **** .
You can resolve this in the following ways:

  • Upgrade Java version to Java 11
  • To retain the Java 1.8 environment, upgrade to Java 1.8.0_261 or a higher patch version to resolve this issue.

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

If you encounter the error DB::Exception: No local available worker group for vw-xxxx while using the system, this is caused by the virtual warehouse not started yet.
You can resolve this in the following ways:
Log in to the ByteHouse cloud data warehouse console. On the virtual warehouse page, check whether your virtual warehouse is in the running status.

Code: UNAUTHENTICATED

If you encounter the Exception: unknown error: Code: UNAUTHENTICATED error during use, this may be caused by incorrect configuration of user and password.
You can resolve this in the following ways:
Please ensure that the configured user and password are correct.

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

If you encounter the DB::Exception: Database xxx.yyy doesn't exist error while using the system, this may be caused by a database name configuration error.
You can resolve this in the following ways:
Please confirm that the database name configured in the connection information is correct.

Exception: No appropriate protocol

If you encounter the Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate) error while using the product, this may be caused by incompatible TLS versions.
You can resolve this using the following methods:
Please add the following parameter to the end of the connection URL: enabledTLSProtocols=TLSv1.2,TLSv1.3.
The examples are as follows:

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