JDBC-драйвер
clickhouse-jdbc реализует стандартный интерфейс JDBC с использованием последней версии Java-клиента.
Рекомендуется использовать последнюю версию Java-клиента напрямую, если критичны производительность или прямой доступ.
Требования к среде
- OpenJDK версии >= 8
Настройка
- Maven
- Gradle (Kotlin)
- Gradle
Конфигурация
Класс драйвера: com.clickhouse.jdbc.ClickHouseDriver
com.clickhouse.jdbc.ClickHouseDriver — это класс-фасад для новой и старой реализаций JDBC. По умолчанию используется новая реализация JDBC.
Чтобы использовать старую реализацию JDBC, установите свойство clickhouse.jdbc.v1 в значение true в параметрах подключения.
com.clickhouse.jdbc.Driver — новая реализация JDBC.
com.clickhouse.jdbc.DriverV1 — старая реализация JDBC.
Синтаксис URL: jdbc:(ch|clickhouse)[:<protocol>]://endpoint[:port][/<database>][?param1=value1¶m2=value2][#tag1,tag2,...], например:
jdbc:clickhouse:http://localhost:8123jdbc:clickhouse:https://localhost:8443?ssl=true
Обратите внимание на следующие особенности синтаксиса URL:
- В URL допускается только одна конечная точка
- протокол следует указывать, если используется не значение по умолчанию — 'HTTP'
- порт следует указывать, если используется порт, отличный от порта по умолчанию '8123'
- драйвер не определяет протокол по номеру порта; его необходимо указывать явно
- Параметр
sslне требуется, если протокол указан.
Свойства соединения
Основные параметры конфигурации определены в Java-клиенте. Их следует передавать драйверу без изменений. Драйвер имеет собственные свойства, которые не входят в конфигурацию клиента; они перечислены ниже.
Свойства драйвера:
| Свойство | Значение по умолчанию | Описание |
|---|---|---|
disable_frameworks_detection | true | Отключить определение фреймворков на основе заголовка User-Agent |
jdbc_ignore_unsupported_values | false | Подавляет SQLFeatureNotSupportedException, если оно не влияет на работу драйвера |
clickhouse.jdbc.v1 | false | Использовать старую реализацию JDBC вместо новой |
default_query_settings | null | Позволяет передавать настройки запроса по умолчанию при выполнении запросов |
jdbc_resultset_auto_close | true | Автоматически закрывает ResultSet при закрытии объекта Statement |
beta.row_binary_for_simple_insert | false | Использовать реализацию PreparedStatement, основанную на записи в формате RowBinary. Работает только для запросов вида INSERT INTO ... VALUES. |
jdbc_resultset_auto_close | true | Автоматически закрывает ResultSet при закрытии объекта Statement |
jdbc_use_max_result_rows | false | Включает использование серверного свойства max_result_rows для ограничения количества строк, возвращаемых запросом. При включении переопределяет режим переполнения, установленный пользователем. Подробности см. в JavaDoc. |
jdbc_sql_parser | JAVACC | Определяет, какой SQL‑парсер будет использоваться. Доступные варианты: ANTLR4, ANTLR4_PARAMS_PARSER, JAVACC. |
Все настройки сервера должны иметь префикс clickhouse_setting_ (аналогично конфигурации клиента).
Пример конфигурации:
что будет эквивалентно следующему JDBC URL:
Примечание: URL-кодирование JDBC URL или свойств не требуется — они будут закодированы автоматически.
Поддерживаемые типы данных
Драйвер JDBC поддерживает те же форматы данных, что и базовый Java-клиент.
Сопоставление типов JDBC
Следующее сопоставление применяется к:
ResultSet#getObject(columnIndex)— этот метод вернёт объект соответствующего класса Java. (Int8->java.lang.Byte,Int16->java.lang.Shortи т.д.)ResultSetMetaData#getColumnType(columnIndex)— этот метод возвращает соответствующий тип JDBC. (Int8->java.lang.Byte,Int16->java.lang.Shortи т. д.)
Существует несколько способов изменить сопоставление:
- Метод
ResultSet#getObject(columnIndex, class)будет пытаться преобразовать значение к типуclass. Для таких преобразований существуют некоторые ограничения. Подробности см. в соответствующих разделах.
Числовые типы
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| Int8 | TINYINT | java.lang.Byte |
| Int16 | SMALLINT | java.lang.Short |
| Int32 | INTEGER | java.lang.Integer |
| Int64 | BIGINT | java.lang.Long |
| Int128 | OTHER | java.math.BigInteger |
| Int256 | OTHER | java.math.BigInteger |
| UInt8 | OTHER | java.lang.Short |
| UInt16 | OTHER | java.lang.Integer |
| UInt32 | OTHER | java.lang.Long |
| UInt64 | OTHER | java.math.BigInteger |
| UInt128 | OTHER | java.math.BigInteger |
| UInt256 | OTHER | java.math.BigInteger |
| Float32 | REAL | java.lang.Float |
| Float64 | DOUBLE | java.lang.Double |
| Decimal32 | DECIMAL | java.math.BigDecimal |
| Decimal64 | DECIMAL | java.math.BigDecimal |
| Decimal128 | DECIMAL | java.math.BigDecimal |
| Decimal256 | DECIMAL | java.math.BigDecimal |
| Bool | BOOLEAN | java.lang.Boolean |
- Числовые типы взаимно преобразуемы. Поэтому
Int8можно получить какFloat64и наоборот.:rs.getObject(1, Float64.class)вернёт значение типаFloat64из столбцаInt8.rs.getLong(1)вернёт значение типаLongиз столбцаInt8.rs.getByte(1)может вернуть значение типаByteиз столбцаInt16, если оно умещается в диапазонByte.
- Преобразование значений из более широкого типа данных в более узкий не рекомендуется из‑за риска повреждения данных.
- Тип
Boolтакже интерпретируется как числовой тип. - Все числовые типы могут быть прочитаны как
java.lang.String.
Строковые типы
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| String | VARCHAR | java.lang.String |
| FixedString | VARCHAR | java.lang.String |
Stringможет быть прочитан только какjava.lang.Stringилиbyte[].FixedStringсчитывается без изменений и дополняется нулевыми байтами до длины столбца. (Например,FixedString(10)для'John'будет прочитан как'John\0\0\0\0\0\0\0\0\0'.)
Типы Enum
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| Enum8 | OTHER | java.lang.String |
| Enum16 | OTHER | java.lang.String |
Enum8иEnum16по умолчанию сопоставляются сjava.lang.String.- Значения Enum могут быть прочитаны как числовые значения с помощью соответствующего метода-геттера или метода
getObject(columnIndex, Integer.class). Enum16внутренне сопоставляется с типом short, а Enum8 — с типом byte. Следует избегать чтенияEnum16как byte из‑за риска повреждения данных.- Значения Enum в
PreparedStatementможно указывать как строковые или числовые значения.
Типы даты и времени
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| Date | DATE | java.sql.Date |
| Date32 | DATE | java.sql.Date |
| DateTime | TIMESTAMP | java.sql.Timestamp |
| DateTime64 | TIMESTAMP | java.sql.Timestamp |
| Time | TIME | java.sql.Time |
| Time64 | TIME | java.sql.Time |
- Типы Date / Time сопоставляются с типами
java.sqlдля лучшей совместимости с JDBC. Однако получить объектыjava.time.LocalDate,java.time.LocalDateTime,java.time.LocalTimeможно, используяResultSet#getObject(columnIndex, Class<T>)и передавая соответствующий класс в качестве второго аргумента.rs.getObject(1, java.time.LocalDate.class)вернёт значение типаjava.time.LocalDateиз столбцаDate.rs.getObject(1, java.time.LocalDateTime.class)вернёт значение типаjava.time.LocalDateTimeиз столбцаDateTime.rs.getObject(1, java.time.LocalTime.class)вернёт значение типаjava.time.LocalTimeиз столбцаTime.
- Типы
Date,Date32,Time,Time64не зависят от часового пояса сервера. DateTime,DateTime64зависят от часового пояса сервера или часового пояса сеанса.DateTimeиDateTime64можно получить какZonedDateTime, используяgetObject(colIndex, ZonedDateTime.class).
Типы сбора данных
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| Array | ARRAY | java.sql.Array |
| Tuple | OTHER | Object[] |
| Map | JAVA_OBJECT | java.util.Map |
Arrayпо умолчанию сопоставляется сjava.sql.Arrayдля совместимости с JDBC. Это также позволяет получить больше информации о возвращаемом значении массива. Это полезно для вывода типов.Arrayреализует методgetResultSet(), возвращающийjava.sql.ResultSetс тем же содержимым, что и исходный массив.- Типы коллекций не следует читать как
java.lang.String, поскольку это некорректный формат представления данных (например, в массиве строковые значения не заключаются в кавычки). Mapсопоставляется типуJAVA_OBJECT, так как значение можно прочитать только с помощью методаgetObject(columnIndex, Class<T>).Mapне являетсяjava.sql.Struct, потому что у него нет именованных столбцов.
Tupleсопоставляется сObject[], поскольку он может содержать элементы разных типов, а использованиеListздесь некорректно.Tupleможет быть прочитан какArrayс помощью методаgetObject(columnIndex, Array.class). В этом случаеArray#baseTypeNameвернёт определение столбца типаTuple.
Геотипы
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| Point | OTHER | double[] |
| Ring | OTHER | double[][] |
| Polygon | OTHER | double[][][] |
| MultiPolygon | OTHER | double[][][][] |
Типы Nullable и LowCardinality
NullableиLowCardinality— это специальные типы-обёртки для других типов.Nullableвлияет на то, как имена типов возвращаются вResultSetMetaData
Специальные типы
| Тип ClickHouse | Тип JDBC | Класс Java |
|---|---|---|
| UUID | OTHER | java.util.UUID |
| IPv4 | OTHER | java.net.Inet4Address |
| IPv6 | OTHER | java.net.Inet6Address |
| JSON | OTHER | java.lang.String |
| AggregateFunction | OTHER | (двоичное представление) |
| SimpleAggregateFunction | (обёрнутый тип) | (обёрнутый класс) |
UUIDне является стандартным типом JDBC. Однако он входит в состав JDK. По умолчанию методgetObject()возвращаетjava.util.UUID.UUIDможно считывать и записывать какStringс помощью методаgetObject(columnIndex, String.class).IPv4иIPv6не относятся к стандартным типам JDBC. Однако они входят в состав JDK. По умолчанию при вызове методаgetObject()возвращаются объекты типовjava.net.Inet4Addressиjava.net.Inet6Address.IPv4иIPv6можно читать и записывать в видеStringс помощью методаgetObject(columnIndex, String.class).
Обработка дат, времени и часовых поясов
java.sql.Date, java.sql.Time и java.sql.Timestamp могут усложнить вычисление часовых поясов — хотя они, разумеется, поддерживаются,
рекомендуется рассмотреть использование пакета java.time. ZonedDateTime и
OffsetDateTime являются отличной заменой для java.sql.Timestamp, java.sql.Date и java.sql.Time.
Date хранится без часового пояса, тогда как DateTime хранится с часовым поясом. Это может привести к неожиданным результатам при неосторожном использовании.
Создание соединения
Предоставление учётных данных и настроек
Простое выражение
Вставка данных
HikariCP
Дополнительная информация
Дополнительную информацию см. в нашем репозитории GitHub и документации Java-клиента.
Устранение неполадок
Логирование
Драйвер использует slf4j для ведения журнала и будет использовать первую доступную реализацию в classpath.
Устранение таймаута JDBC при больших вставках данных
При выполнении больших вставок в ClickHouse с длительным временем выполнения могут возникать ошибки тайм-аута JDBC, такие как:
Эти ошибки могут нарушить процесс вставки данных и повлиять на стабильность системы. Чтобы устранить эту проблему, может потребоваться настроить несколько параметров таймаута в операционной системе клиента.
macOS
В macOS можно настроить следующие параметры для решения проблемы:
net.inet.tcp.keepidle: 60000net.inet.tcp.keepintvl: 45000net.inet.tcp.keepinit: 45000net.inet.tcp.keepcnt: 8net.inet.tcp.always_keepalive: 1
Linux
В Linux одних только эквивалентных настроек может быть недостаточно для решения проблемы. Необходимы дополнительные действия из-за особенностей обработки параметров keep-alive для сокетов в Linux. Выполните следующие действия:
- Настройте следующие параметры ядра Linux в
/etc/sysctl.confили соответствующем конфигурационном файле:
net.inet.tcp.keepidle: 60000net.inet.tcp.keepintvl: 45000net.inet.tcp.keepinit: 45000net.inet.tcp.keepcnt: 8net.inet.tcp.always_keepalive: 1net.ipv4.tcp_keepalive_intvl: 75net.ipv4.tcp_keepalive_probes: 9net.ipv4.tcp_keepalive_time: 60 (можно рассмотреть возможность уменьшения этого значения по сравнению со значением по умолчанию — 300 секунд)
- После изменения параметров ядра примените изменения, выполнив следующую команду:
После настройки этих параметров необходимо убедиться, что ваш клиент включает опцию Keep Alive для сокета:
Руководство по миграции
Основные изменения
| Возможность | V1 (устаревшая) | V2 (новая) |
|---|---|---|
| Поддержка транзакций | Частично поддерживается | Не поддерживается |
| Переименование столбцов в результирующем наборе | Частично поддерживается | Не поддерживается |
| SQL с несколькими операторами | Не поддерживается | Недоступно |
| Именованные параметры запроса | Поддерживается | Не поддерживается (отсутствует в спецификации JDBC) |
Потоковая передача данных с помощью PreparedStatement | Поддерживается | Не поддерживается |
- JDBC V2 реализован как более легковесная версия, поэтому часть возможностей была удалена.
- Потоковая передача данных не поддерживается в JDBC V2, так как она не входит ни в спецификацию JDBC, ни в стандарт Java.
- JDBC V2 требует явной конфигурации. Настройки отказоустойчивости по умолчанию отсутствуют.
- Протокол должен явно указываться в URL. Определение его по номеру порта не производится.
Изменения конфигурации
Доступны только два перечисления:
com.clickhouse.jdbc.DriverProperties— собственные параметры конфигурации драйвера.com.clickhouse.client.api.ClientConfigProperties— свойства конфигурации клиента. Изменения конфигурации клиента описаны в документации по Java‑клиенту.
Свойства подключения разбираются следующим образом:
- Сначала свойства извлекаются из URL; они имеют приоритет над всеми остальными свойствами.
- Свойства драйвера не передаются клиенту.
- Endpoints (host, port, protocol) извлекаются из URL.
Пример:
Изменения типов данных
Числовые типы
| Тип в ClickHouse | Совместимость с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| Int8 | ✅ | TINYINT | java.lang.Byte | TINYINT | java.lang.Byte |
| Int16 | ✅ | SMALLINT | java.lang.Short | SMALLINT | java.lang.Short |
| Int32 | ✅ | INTEGER | java.lang.Integer | INTEGER | java.lang.Integer |
| Int64 | ✅ | BIGINT | java.lang.Long | BIGINT | java.lang.Long |
| Int128 | ✅ | OTHER | java.math.BigInteger | OTHER | java.math.BigInteger |
| Int256 | ✅ | OTHER | java.math.BigInteger | OTHER | java.math.BigInteger |
| UInt8 | ❌ | OTHER | java.lang.Short | OTHER | com.clickhouse.data.value.UnsignedByte |
| UInt16 | ❌ | OTHER | java.lang.Integer | OTHER | com.clickhouse.data.value.UnsignedShort |
| UInt32 | ❌ | OTHER | java.lang.Long | OTHER | com.clickhouse.data.value.UnsignedInteger |
| UInt64 | ❌ | OTHER | java.math.BigInteger | OTHER | com.clickhouse.data.value.UnsignedLong |
| UInt128 | ✅ | OTHER | java.math.BigInteger | OTHER | java.math.BigInteger |
| UInt256 | ✅ | OTHER | java.math.BigInteger | OTHER | java.math.BigInteger |
| Float32 | ✅ | REAL | java.lang.Float | REAL | java.lang.Float |
| Float64 | ✅ | DOUBLE | java.lang.Double | DOUBLE | java.lang.Double |
| Decimal32 | ✅ | DECIMAL | java.math.BigDecimal | DECIMAL | java.math.BigDecimal |
| Decimal64 | ✅ | DECIMAL | java.math.BigDecimal | DECIMAL | java.math.BigDecimal |
| Decimal128 | ✅ | DECIMAL | java.math.BigDecimal | DECIMAL | java.math.BigDecimal |
| Decimal256 | ✅ | DECIMAL | java.math.BigDecimal | DECIMAL | java.math.BigDecimal |
| Bool | ✅ | BOOLEAN | java.lang.Boolean | BOOLEAN | java.lang.Boolean |
- Ключевое отличие в том, что беззнаковые типы сопоставляются со стандартными типами Java для повышения переносимости.
Строковые типы
| Тип ClickHouse | Совместимость с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| String | ✅ | VARCHAR | java.lang.String | VARCHAR | java.lang.String |
| FixedString | ✅ | VARCHAR | java.lang.String | VARCHAR | java.lang.String |
FixedStringчитается «как есть» в обеих версиях. Например,FixedString(10)для'John'будет прочитан как'John\0\0\0\0\0\0\0\0\0'.- Когда используется
PreparedStatement#setBytes, значение будет преобразовано вunhex('<hex_string>'), а затем интерпретировано какString.
Типы даты и времени
| Тип ClickHouse | Совместимость с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| Date | ❌ | DATE | java.sql.Date | DATE | java.time.LocalDate |
| Date32 | ❌ | DATE | java.sql.Date | DATE | java.time.LocalDate |
| DateTime | ❌ | TIMESTAMP | java.sql.Timestamp | TIMESTAMP | java.time.OffsetDateTime |
| DateTime64 | ❌ | TIMESTAMP | java.sql.Timestamp | TIMESTAMP | java.time.OffsetDateTime |
| Time | ✅ | TIME | java.sql.Time | новый тип / не поддерживается | новый тип / не поддерживается |
| Time64 | ✅ | TIME | java.sql.Time | новый тип / не поддерживается | новый тип / не поддерживается |
TimeиTime64поддерживаются в V2 только как новые типы данных.DateTimeиDateTime64сопоставляются сjava.sql.Timestampдля лучшей совместимости с JDBC.
Типы Enum
| Тип ClickHouse | Совместимость с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| Enum | ✅ | VARCHAR | java.lang.String | OTHER | java.lang.String |
| Enum8 | ✅ | VARCHAR | java.lang.String | OTHER | java.lang.String |
| Enum16 | ✅ | VARCHAR | java.lang.String | OTHER | java.lang.String |
Типы сбора данных
| Тип ClickHouse | Совместимо с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| Array | ❌ | ARRAY | java.sql.Array | ARRAY | Object[] или массив примитивных типов |
| Tuple | ❌ | OTHER | Object[] | STRUCT | java.sql.Struct |
| Map | ❌ | JAVA_OBJECT | java.util.Map | STRUCT | java.util.Map |
- В V2
Arrayпо умолчанию сопоставляется сjava.sql.Arrayдля совместимости с JDBC. Это также позволяет получить больше информации о возвращаемом значении массива. Это полезно для вывода типов. - В версии V2
Arrayреализует методgetResultSet(), который возвращаетjava.sql.ResultSetс тем же содержимым, что и у исходного массива. - V1 использует
STRUCTдляMap, но всегда возвращает объектjava.util.Map. V2 исправляет это, сопоставляяMapсJAVA_OBJECT. Кроме того,STRUCTявляется некорректным типом дляMap, так какMapне имеет именованных столбцов. - V1 использует
STRUCTдляTuple, но всегда возвращает объект типаList<Object>. V2 исправляет это, сопоставляяTupleсOTHERи возвращаетObject[], поскольку использованиеListнекорректно: в кортеже могут присутствовать элементы разных типов. - Методы
PreparedStatement#setBytesиResultSet#getBytesнельзя использовать для работы с типами коллекций. Эти методы предназначены для работы с двоичными строками. - Обычно для записи и чтения типов
Arrayиспользуетсяjava.sql.Array. Драйвер JDBC полностью это поддерживает.
Геотипы
| Тип ClickHouse | Совместимость с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| Point | ✅ | OTHER | double[] | OTHER | double[] |
| Ring | ✅ | OTHER | double[][] | OTHER | double[][] |
| Polygon | ✅ | OTHER | double[][][] | OTHER | double[][][] |
| MultiPolygon | ✅ | OTHER | double[][][][] | OTHER | double[][][][] |
Типы Nullable и LowCardinality
NullableиLowCardinality— специальные типы-обёртки для других типов.- В V2 эти типы не изменялись.
Специальные типы
| Тип ClickHouse | Совместимость с V1 | Тип JDBC (V2) | Класс Java (V2) | Тип JDBC (V1) | Класс Java (V1) |
|---|---|---|---|---|---|
| JSON | ❌ | OTHER | java.lang.String | не поддерживается | не поддерживается |
| AggregateFunction | ✅ | OTHER | (двоичное представление) | OTHER | (двоичное представление) |
| SimpleAggregateFunction | ✅ | (тип-обёртка) | (класс-обёртка) | (тип-обёртка) | (класс-обёртка) |
| UUID | ✅ | OTHER | java.util.UUID | VARCHAR | java.util.UUID |
| IPv4 | ✅ | OTHER | java.net.Inet4Address | VARCHAR | java.net.Inet4Address |
| IPv6 | ✅ | OTHER | java.net.Inet6Address | VARCHAR | java.net.Inet6Address |
| Dynamic | ❌ | OTHER | java.Object | Не поддерживается | Не поддерживается |
| Variant | ❌ | OTHER | java.Object | Не поддерживается | Не поддерживается |
- V1 использует
VARCHARдляUUID, но всегда возвращает объектjava.util.UUID. V2 исправляет это, сопоставляяUUIDсOTHERи также возвращая объектjava.util.UUID. - V1 использует
VARCHARдляIPv4иIPv6, но при этом всегда возвращает объектыjava.net.Inet4Addressиjava.net.Inet6Address. V2 исправляет это, сопоставляяIPv4иIPv6сOTHERи возвращаяjava.net.Inet4Addressиjava.net.Inet6Address. DynamicиVariant— новые типы в V2. В V1 не поддерживаются.ТипJSONоснован на типеDynamic, поэтому поддерживается только в V2.- Значения IPv4 и IPv6 можно считывать как массив байт (
byte[]), используя методgetBytes(columnIndex). Однако рекомендуется использовать специальные классы, предназначенные для этих типов. - V2 не поддерживает чтение IP‑адресов как чисел, так как преобразование лучше реализовано средствами классов InetAddress.
Изменения метаданных базы данных
- V2 использует только термин
Schemaдля именования баз данных. ТерминCatalogзарезервирован для будущего использования. - V2 возвращает
falseдляDatabaseMetaData.supportsTransactions()иDatabaseMetaData.supportsSavepoints(). Это поведение будет изменено в последующих версиях.