Skip to content
3 changes: 2 additions & 1 deletion docs/en/integrations/language-clients/java/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import CodeBlock from '@theme/CodeBlock';

- [Client-V2](./client-v2.md)
- [Client-V1 (Old)](./client-v1.md)
- [JDBC Driver](./jdbc-driver.md)
- [JDBC-V2](./jdbc-v2.md)
- [JDBC-V1 (Old)](./jdbc-v1.md)
- [R2DBC Driver](./r2dbc.md)

## ClickHouse Client
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
sidebar_label: JDBC Driver
sidebar_position: 4
sidebar_label: JDBC V1 (Old)
sidebar_position: 5
keywords: [clickhouse, java, jdbc, driver, integrate]
description: ClickHouse JDBC driver
slug: /en/integrations/java/jdbc-driver
description: ClickHouse JDBC driver V1 (outdated)
slug: /en/integrations/java/jdbc-v1
---

import Tabs from '@theme/Tabs';
Expand All @@ -16,7 +16,7 @@ import CodeBlock from '@theme/CodeBlock';
`clickhouse-jdbc` implements the standard JDBC interface. Being built on top of [clickhouse-client](/docs/en/integrations/sql-clients/sql-console), it provides additional features like custom type mapping, transaction support, and standard synchronous `UPDATE` and `DELETE` statements, etc., so that it can be easily used with legacy applications and tools.

:::note
Latest JDBC (0.7.2) version uses Client-V1
Latest JDBC (0.7.2) version uses Client-V1
:::

`clickhouse-jdbc` API is synchronous, and generally, it has more overheads(e.g., SQL parsing and type mapping/conversion, etc.). Consider [clickhouse-client](/docs/en/integrations/sql-clients/sql-console) when performance is critical or if you prefer a more direct way to access ClickHouse.
Expand Down Expand Up @@ -121,14 +121,14 @@ Note: please refer to [JDBC specific configuration](https://github.com/ClickHous

## Supported data types

JDBC Driver supports same data formats as client library does.
JDBC Driver supports same data formats as client library does.

:::note
- AggregatedFunction - :warning: does not support `SELECT * FROM table ...`
- Decimal - `SET output_format_decimal_trailing_zeros=1` in 21.9+ for consistency
- Enum - can be treated as both string and integer
- UInt64 - mapped to `long` (in client-v1)
:::
- UInt64 - mapped to `long` (in client-v1)
:::

## Creating Connection

Expand Down Expand Up @@ -160,7 +160,7 @@ try (Connection conn = dataSource.getConnection(...);

:::note
- Use `PreparedStatement` instead of `Statement`
:::
:::

It's easier to use but slower performance compare to input function (see below):

Expand Down Expand Up @@ -194,7 +194,7 @@ try (PreparedStatement ps = conn.prepareStatement(

### Insert with placeholders

This option is recommended only for small inserts because it would require a long SQL expression (that will be parsed on client side and it will consume CPU & Memory):
This option is recommended only for small inserts because it would require a long SQL expression (that will be parsed on client side and it will consume CPU & Memory):

```java showLineNumbers
try (PreparedStatement ps = conn.prepareStatement("insert into mytable values(trim(?),?,?)")) {
Expand Down
236 changes: 236 additions & 0 deletions docs/en/integrations/language-clients/java/jdbc-v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
---
sidebar_label: JDBC V2
sidebar_position: 4
keywords: [clickhouse, java, jdbc, driver, integrate]
description: ClickHouse JDBC driver V2
Copy link
Member

@mshustov mshustov Jan 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I agree with this sentiment, it also might be worth us exploring at this point how do we do "versioning" of the documentation rather than having "extra pages" - like having a version drop down and corresponding version in the URL.

@laeg What about using the client versioning? There will be 2 pages:

  1. description: ClickHouse JDBC driver > v0.8.x (or ClickHouse JDBC driver latest)
  2. description: ClickHouse JDBC driver v0.7.x

We can manually add more pages if necessary and they always transparently mapped to JDBC release version

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah i would prefer if we aligned it more to release versions rather than internal code versions.

did we look into whether we could do something more elegant for versioning the docs?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did we look into whether we could do something more elegant for versioning the docs?

I didn't manage to find a solution in 30min.

slug: /en/integrations/java/jdbc-v2
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';


# JDBC Driver

`clickhouse-jdbc` implements the standard JDBC interface using [client-v2](/docs/en/integrations/language-clients/java/client-v2.md).
We recommend using [client-v2](/docs/en/integrations/language-clients/java/client-v2.md) directly if performance/direct access is critical.

## Changes from 0.7.x
In 0.8 we tried to make the driver more strictly follow the JDBC specification, so there are some removed features that may affect you:

| Old Feature | Notes |
|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Transaction Support | Early versions of the driver only **simulated** transaction support, which could have unexpected results. |
| Response Column Renaming | ResultSets were mutable - for efficiency sake they're now read-only |
| Multi-Statement SQL | Multi-statement support was only **simulated**, now it strictly follows 1:1 |
| Named Parameters | Not part of the JDBC spec |
| Stream-based PreparedStatements | Early version of the driver allowed for non-jdbc usage of PreparedStatements - if you desire such options, we recommend looking at [Client-V2](/docs/en/integrations/language-clients/java/client-v2.md) and its [examples](https://github.com/ClickHouse/clickhouse-java/tree/main/examples/client-v2). |

### Handling Dates, Times, and Timezones
Copy link
Member

@mshustov mshustov Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️ to this section.
A minor ask: could you move it to Supported data types section?

java.sql.Date, java.sql.Time, and java.sql.Timestamp can complicate how Timezones are calculated - though they're of course supported,
you may want to consider using the [java.time](https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) package for new code. [ZonedDateTime](https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html) and
[OffsetDateTime](https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html) are great replacements for java.sql.Timestamp,
and [LocalDateTime](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html) could be used for java.sql.Date and java.sql.Time (though the JDBC driver will assume local
timezone if no calendar is provided).

:::note
`Date` is stored without timezone, while `DateTime` is stored with timezone. This can lead to unexpected results if you're not careful.
:::

## Environment requirements

- [OpenJDK](https://openjdk.java.net) version >= 8

### Setup

<Tabs groupId="jdbc-base-dependencies">
<TabItem value="maven" label="Maven" >

```xml
<!-- https://mvnrepository.com/artifact/com.clickhouse/clickhouse-jdbc -->
<dependency>
<groupId>com.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>0.8.0</version>
<classifier>shaded-all</classifier>
</dependency>
```

</TabItem>
<TabItem value="gradle-kt" label="Gradle (Kotlin)">

```kotlin
// https://mvnrepository.com/artifact/com.clickhouse/clickhouse-jdbc
implementation("com.clickhouse:clickhouse-jdbc:0.8.0:shaded-all")
```
</TabItem>
<TabItem value="gradle" label="Gradle">

```groovy
// https://mvnrepository.com/artifact/com.clickhouse/clickhouse-jdbc
implementation 'com.clickhouse:clickhouse-jdbc:0.8.0:shaded-all'
```

</TabItem>
</Tabs>

## Configuration

**Driver Class**: `com.clickhouse.jdbc.ClickHouseDriver`

**URL Syntax**: `jdbc:(ch|clickhouse)[:<protocol>]://endpoint1[,endpoint2,...][/<database>][?param1=value1&param2=value2][#tag1,tag2,...]`, for example:

- `jdbc:clickhouse:http://localhost:8123`
- `jdbc:clickhouse:https://localhost:8443?ssl=true`

**Connection Properties**:

Beyond standard JDBC properties, the driver supports the ClickHouse-specific properties offered by the underlying [client](/docs/en/integrations/language-clients/java/client-v2.md).
Where possible methods will return an `SQLFeatureNotSupportedException` if the feature is not supported. Other custom properties include:

| Property | Default | Description |
|----------------------------------|---------|----------------------------------------------------------------|
| `disable_frameworks_detection` | `true` | Disable frameworks detection for User-Agent |
| `jdbc_ignore_unsupported_values` | `false` | Suppresses `SQLFeatureNotSupportedException` |
| `clickhouse.jdbc.v1` | `false` | Use JDBC-V1 instead of JDBC-V2 |
| `default_query_settings` | `null` | Allows passing of default query settings with query operations |

## Supported data types

JDBC Driver supports the same data formats as the underlying [client](/docs/en/integrations/language-clients/java/client-v2.md).

## Creating Connection

```java
String url = "jdbc:ch://my-server:8123/system";

Properties properties = new Properties();
DataSource dataSource = new DataSource(url, properties);//DataSource or DriverManager are the main entry points
try (Connection conn = dataSource.getConnection()) {
... // do something with the connection
```

## Supplying Credentials and Settings

```java showLineNumbers
String url = "jdbc:ch://localhost:8123?jdbc_ignore_unsupported_values=true&socket_timeout=10";

Properties info = new Properties();
info.put("user", "default");
info.put("password", "password");
info.put("database", "some_db");

//Creating a connection with DataSource
DataSource dataSource = new DataSource(url, info);
try (Connection conn = dataSource.getConnection()) {
... // do something with the connection
}

//Alternate approach using the DriverManager
try (Connection conn = DriverManager.getConnection(url, info)) {
... // do something with the connection
}
```

## Simple Statement

```java showLineNumbers

try (Connection conn = dataSource.getConnection(...);
Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery("select * from numbers(50000)");
while(rs.next()) {
// ...
}
}
```

## Insert

```java showLineNumbers
try (PreparedStatement ps = conn.prepareStatement("INSERT INTO mytable VALUES (?, ?)")) {
ps.setString(1, "test"); // id
ps.setObject(2, LocalDateTime.now()); // timestamp
ps.addBatch();
...
ps.executeBatch(); // stream everything on-hand into ClickHouse
}
```

## Hikari

```java showLineNumbers
// connection pooling won't help much in terms of performance,
// because the underlying implementation has its own pool.
// for example: HttpURLConnection has a pool for sockets
HikariConfig poolConfig = new HikariConfig();
poolConfig.setConnectionTimeout(5000L);
poolConfig.setMaximumPoolSize(20);
poolConfig.setMaxLifetime(300_000L);
poolConfig.setDataSource(new ClickHouseDataSource(url, properties));

try (HikariDataSource ds = new HikariDataSource(poolConfig);
Connection conn = ds.getConnection();
Statement s = conn.createStatement();
ResultSet rs = s.executeQuery("SELECT * FROM system.numbers LIMIT 3")) {
while (rs.next()) {
// handle row
log.info("Integer: {}, String: {}", rs.getInt(1), rs.getString(1));//Same column but different types
}
}
```

## More Information
For more information, see our [GitHub repository](https://github.com/ClickHouse/clickhouse-java) and [Client-V2 documentation](/docs/en/integrations/language-clients/java/client-v2.md).


## Troubleshooting
### Logging
The driver uses [slf4j](https://www.slf4j.org/) for logging, and will use the first available implementation on the classpath.

### Resolving JDBC Timeout on Large Inserts

When performing large inserts in ClickHouse with long execution times, you may encounter JDBC timeout errors like:

```plaintext
Caused by: java.sql.SQLException: Read timed out, server myHostname [uri=https://hostname.aws.clickhouse.cloud:8443]
```
These errors can disrupt the data insertion process and affect system stability. To address this issue you may need to adjust a few timeout settings in the client's OS.

#### Mac OS

On Mac OS, the following settings can be adjusted to resolve the issue:

- `net.inet.tcp.keepidle`: 60000
- `net.inet.tcp.keepintvl`: 45000
- `net.inet.tcp.keepinit`: 45000
- `net.inet.tcp.keepcnt`: 8
- `net.inet.tcp.always_keepalive`: 1

#### Linux

On Linux, the equivalent settings alone may not resolve the issue. Additional steps are required due to the differences in how Linux handles socket keep-alive settings. Follow these steps:

1. Adjust the following Linux kernel parameters in `/etc/sysctl.conf` or a related configuration file:

- `net.inet.tcp.keepidle`: 60000
- `net.inet.tcp.keepintvl`: 45000
- `net.inet.tcp.keepinit`: 45000
- `net.inet.tcp.keepcnt`: 8
- `net.inet.tcp.always_keepalive`: 1
- `net.ipv4.tcp_keepalive_intvl`: 75
- `net.ipv4.tcp_keepalive_probes`: 9
- `net.ipv4.tcp_keepalive_time`: 60 (You may consider lowering this value from the default 300 seconds)

2. After modifying the kernel parameters, apply the changes by running the following command:

```shell
sudo sysctl -p
```

After Setting those settings, you need to ensure that your client enables the Keep Alive option on the socket:

```java
properties.setProperty("socket_keepalive", "true");
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see a few issues with docs label. should we address them from the very beginning? https://github.com/ClickHouse/clickhouse-java/issues?q=is%3Aissue%20state%3Aopen%20label%3Adocs%20label%3Ajdbc-v2

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can do it a in follow-up

3 changes: 2 additions & 1 deletion sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,8 @@ const sidebars = {
// "en/integrations/language-clients/java/index",
"en/integrations/language-clients/java/client-v2",
"en/integrations/language-clients/java/client-v1",
"en/integrations/language-clients/java/jdbc-driver",
"en/integrations/language-clients/java/jdbc-v2",
"en/integrations/language-clients/java/jdbc-v1",
"en/integrations/language-clients/java/r2dbc"
]
},
Expand Down
Loading