Перейти к основному содержанию
clickhouse-jdbc реализует стандартный интерфейс JDBC на базе новейшего Java-клиента. Если критически важны производительность и прямой доступ, рекомендуем использовать новейший Java-клиент напрямую.

Требования к среде

Setup

Если вы используете JDBC driver в приложении, которое требует добавления jar-файла в classpath, скачайте jar-файл по адресу:

Конфигурация

Класс драйвера: com.clickhouse.jdbc.ClickHouseDriver
com.clickhouse.jdbc.ClickHouseDriver — это фасадный класс для новой и старой реализаций JDBC. По умолчанию он использует новую реализацию JDBC. Старую реализацию JDBC можно использовать, установив system-свойство clickhouse.jdbc.v1 в значение true. Это свойство нужно установить до обращения к классу Driver.Альтернативный способ переключения между версиями — напрямую использовать классы Driver соответствующей версии:
  • com.clickhouse.jdbc.Driver — новая реализация JDBC (V2).
  • com.clickhouse.jdbc.DriverV1 — старая реализация JDBC (V1).
Синтаксис URL: jdbc:(ch|clickhouse)[:<protocol>]://endpoint[:port][/<database>][?param1=value1&param2=value2][#tag1,tag2,...], например:
  • jdbc:clickhouse:http://localhost:8123
  • jdbc:clickhouse:https://localhost:8443?ssl=true
Обратите внимание на несколько особенностей синтаксиса URL:
  • В URL допускается только одна конечная точка
  • протокол следует указывать, если используется не значение по умолчанию — ‘HTTP’
  • порт следует указать, если используется не стандартный порт ‘8123’
  • драйвер не пытается определить протокол по порту, его нужно указать явно
  • Параметр ssl не требуется, если указан протокол.

Свойства подключения

Основные параметры конфигурации определены в разделе Java-клиента. Их следует передавать в драйвер без изменений. Драйвер также имеет ряд собственных свойств, не входящих в конфигурацию клиента; они перечислены ниже.Свойства драйвера:
Настройки сервераВсе настройки сервера должны иметь префикс clickhouse_setting_ (как и в конфигурации клиента).
Пример конфигурации:
что будет эквивалентно следующему JDBC URL:
Примечание: кодировать JDBC URL или свойства в формате URL не нужно — они будут закодированы автоматически.Профили только для чтенияМы намеренно не добавляем настройки по умолчанию в свойства подключения, чтобы избежать проблем с профилями только для чтения. Однако некоторым пользователям необходимо передавать настройки формата (например, для чтения JSON как String), и в таких случаях мы рекомендуем использовать профиль readonly=2. Подробнее о профилях только для чтения читайте здесь.

Идентификация клиента

Существует два способа идентифицировать приложение, из которого поступил запрос: задать com.clickhouse.client.api.ClientConfigProperties#CLIENT_NAME через параметры подключения или использовать метод java.sql.Connection#setClientInfo(String name, String value).
showLineNumbers
showLineNumbers
Оба способа дадут следующее значение http_user_agent в журнале запросов:
Примечание: Рекомендуем использовать формат app_name/version для свойства client_name — это помогает идентифицировать приложение в журнале запросов.

Идентификация операции

JDBC driver генерирует query_id для каждой операции (в настоящее время он включён в исключения сервера).Чтобы задать log_comment для операции, используйте метод com.clickhouse.jdbc.StatementImpl#getLocalSettings. Для этого необходимо сначала привести Statement или PreparedStatement к типу com.clickhouse.jdbc.StatementImpl.
showLineNumbers
Примечание: данный подход работает только для однопоточного использования оператора, так как localSettings является общим для всех потоков.

Поддерживаемые типы данных

JDBC driver поддерживает те же форматы данных, что и базовый 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. Существуют некоторые ограничения на преобразование. Подробнее см. в соответствующих разделах.
Числовые типы
  • числовые типы можно преобразовывать друг в друга. Поэтому Int8 можно получить как Float64 и наоборот.:
    • rs.getObject(1, Float64.class) вернёт значение типа Float64 из столбца Int8.
    • rs.getLong(1) вернёт значение типа Long из столбца Int8.
    • rs.getByte(1) может вернуть значение типа Byte из столбца Int16, если оно помещается в Byte.
  • Преобразование из более широкого типа в более узкий не рекомендуется из-за риска повреждения данных.
  • Тип Bool также может использоваться как число.
  • Все числовые типы можно считывать как java.lang.String.
  • При сохранении Float.MAX_VALUE из Java как Float возникает проблема (https://github.com/ClickHouse/clickhouse-java/issues/809). Если сохранить то же значение как Double, проблема исчезает.
Строковые типы
  • String можно считывать только как java.lang.String или byte[].
  • FixedString считывается как есть и дополняется нулями до длины столбца. (Например, FixedString(10) для 'John' будет считан как 'John\0\0\0\0\0\0\0\0\0'.)
Типы Enum
  • Enum8 и Enum16 по умолчанию соответствуют типу java.lang.String.
  • Значения enum можно считывать как числовые, используя соответствующий геттер или метод getObject(columnIndex, Integer.class).
  • Enum16 внутренне представлен как short, а Enum8 — как byte. Следует избегать чтения Enum16 как byte из-за риска повреждения данных.
  • Значения enum можно задавать в PreparedStatement как строковые или числовые.
Типы даты/времени
  • Типы 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).
Вложенные типы
  • Array по умолчанию сопоставляется с java.sql.Array для совместимости с JDBC. Это также позволяет предоставить больше информации о возвращаемом значении массива. Полезно для вывода типов.
  • Array реализует метод getResultSet(), который возвращает java.sql.ResultSet с тем же содержимым, что и исходный массив.
  • Типы коллекций не следует считывать как java.lang.String, поскольку это недопустимый способ представления данных (например, в массиве строковые значения не заключаются в кавычки).
  • Map сопоставляется с OTHER, потому что значение можно получить только с помощью метода getObject(columnIndex, Class<T>).
    • Map не является java.sql.Struct, поскольку у него нет именованных столбцов.
  • Tuple сопоставляется с Object[], поскольку он может содержать значения разных типов, а использовать List нельзя.
  • Tuple можно считать как Array с помощью метода getObject(columnIndex, Array.class). В этом случае Array#baseTypeName вернёт определение столбца Tuple.
Метаданные типа элементов массиваArray.getBaseTypeName() возвращает имя типа элемента ClickHouse; Array.getBaseType() возвращает код типа JDBC. JDBC V2 сохраняет полные сигнатуры типов (типы-обёртки, параметры типов), которые V1 отбрасывает.Общие правила соответствия для массивов:Notes on the rules above:
  • Типы-обёртки (Nullable, LowCardinality) сохраняются в getBaseTypeName(), но getBaseType() возвращает JDBC-код внутреннего типа.
  • Вложенные массивы в метаданных представлены в развёрнутом виде: getBaseTypeName() возвращает тип самого глубоко вложенного элемента, не являющегося массивом, а не тип непосредственного дочернего элемента.
  • Параметризованные типы (FixedString(N), полные определения Enum/Tuple) сохраняют свои параметры в getBaseTypeName().
Примеры:
  • В V2 getBaseTypeName() сохраняет полную сигнатуру типа, включая типы-обёртки (Nullable, LowCardinality) и параметры типа (FixedString(8), полные определения Enum и Tuple). V1 убирает их и возвращает только имя базового типа.
  • Массивы Tuple в V2 используют OTHER (1111) вместо STRUCT (2002), потому что кортежи ClickHouse имеют именованные поля, а java.sql.Struct их не поддерживает.
  • Массивы UUID в V2 используют OTHER (1111), что соответствует сопоставлению скалярного UUID.
  • Значения Enum сопоставляются с VARCHAR — элементы enum идентифицируются по строковому имени независимо от базовой числовой кодировки.
Запись массивовИспользуйте java.sql.Connection#createArrayOf для создания экземпляра объекта java.sql.Array. Этот объект предназначен для унификации работы с массивами в различных базах данных. Соединение необходимо для передачи конфигурации в фабричный метод Array.Метод принимает два аргумента:
  • typeName — имя типа элементов массива. Например: Array(Int32) -> "Int32".
  • elements — сами элементы массива. Например, [[1, 2, 3], [4, 5, 6]] -> new Integer[][] {{1, 2, 3}, {4, 5, 6}}.
Tuple может быть представлен как Object[] или как java.sql.Struct (см. раздел о записи Tuple ниже).Пример
Чтение массивовИспользуйте ResultSet#getArray(columnIndex) для чтения объекта Array. Объект позволяет обращаться к массивам любой глубины вложенности. Метод Array#getResultSet() можно использовать для чтения элементов массива в более унифицированном виде в качестве java.sql.ResultSet. Это удобно, когда точный тип элементов массива неизвестен.Пример
Запись TupleЗначения типа Tuple сопоставляются с объектом com.clickhouse.data.Tuple и должны записываться как этот объект с помощью вызова метода setObject(columnIndex, tuple). Для большей переносимости можно использовать объект java.sql.Struct для записи значений типа Tuple.Пример
Чтение TupleМетод getObject(columnIndex) возвращает Object[]. Tuple можно считать как java.sql.Array с помощью метода getObject(columnIndex, Array.class).Пример
Запись значений типа MapMap можно записать только как объект java.collections.Map, поскольку этот тип требует пар ключ-значение (java.sql.Struct не поддерживает пары ключ-значение).Пример
Чтение значений типа MapMap можно считать как объект java.collections.Map с помощью метода getObject(columnIndex, Map.class).Пример
Запись NestedИспользуйте java.sql.Connection#createStruct для создания экземпляра объекта java.sql.Struct. Этот объект предназначен для унификации обработки вложенных структур в различных базах данных. Соединение необходимо для передачи конфигурации в фабричный метод Struct.Метод принимает два аргумента:
  • typeName — имя типа вложенных элементов. Например: Nested(Tuple(Int32, String)) -> "Nested(Tuple(Int32, String))".
  • elements — сами вложенные элементы. Например, [1, 'test'] -> new Object[] {1, 'test'}.
Пример
Чтение вложенных данныхИспользуйте ResultSet#getStruct(columnIndex, StructDescriptor) для чтения объекта Nested. Объект позволяет обращаться к вложенным элементам любой глубины вложенности. Метод Struct#getResultSet() можно использовать для чтения вложенных элементов в более унифицированном виде — в форме java.sql.ResultSet. Это удобно, когда точный тип вложенных элементов неизвестен.Пример
Гео-типыТипы Nullable и LowCardinality
  • Nullable и LowCardinality — это специальные типы, которые являются оболочками для других типов.
  • Nullable влияет на то, как в ResultSetMetaData возвращаются имена типов
Специальные типы
  • 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).
Тип JSONПо умолчанию тип JSON сопоставляется с Map<String, Object>, где ключи — это ключи объекта JSON, а значения — значения объекта JSON. Например:
будет преобразовано в:
Существует более удобный способ считывать JSON как String — передать настройку сервера jdbc_read_json_as_string=true в свойства подключения. Это заставляет драйвер возвращать значения JSON как String, которые затем можно разобрать с помощью любой JSON-библиотеки.
Начиная с ClickHouse версии 25.8 числа по умолчанию больше не заключаются в кавычки. Для более старых версий можно отключить заключение в кавычки, передав настройки сервера в свойства подключения:

Работа с датами, временем и часовыми поясами

Ознакомьтесь с руководством по Date/Time, в котором описаны типичные проблемы и логика работы драйвера при обработке значений Date/Time и временных меток.

Создание подключения

Передача учётных данных и настроек

showLineNumbers

Простой оператор

showLineNumbers

Вставка

showLineNumbers

HikariCP

showLineNumbers

Дополнительная информация

Дополнительную информацию см. в нашем репозитории GitHub и документации по Java-клиенту.

Устранение неполадок

Логирование

Драйвер использует slf4j для логирования и задействует первую доступную реализацию в classpath.

Устранение тайм-аута JDBC при больших вставках

При выполнении больших операций вставки в ClickHouse с длительным временем выполнения могут возникать ошибки тайм-аута JDBC, например:
Эти ошибки могут нарушить процесс вставки данных и повлиять на стабильность системы. Для решения этой проблемы может потребоваться скорректировать несколько параметров тайм-аута в ОС клиента.

Mac OS

В Mac OS для решения этой проблемы можно изменить следующие настройки:
  • 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

В Linux одних только аналогичных настроек может оказаться недостаточно для решения проблемы. Из-за различий в том, как Linux обрабатывает настройки keep-alive для сокетов, потребуются дополнительные шаги. Выполните следующие действия:
  1. Настройте следующие параметры ядра Linux в /etc/sysctl.conf или соответствующем файле конфигурации:
  • 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 (При необходимости можно уменьшить это значение по сравнению со значением по умолчанию — 300 секунд)
  1. После изменения параметров ядра примените их, выполнив следующую команду:
После настройки этих параметров необходимо убедиться, что клиент включает опцию Keep Alive для сокета:

Руководство по миграции

Основные изменения

  • JDBC V2 реализован в более облегчённом виде, и некоторые возможности были удалены.
    • Потоковая передача данных не поддерживается в JDBC V2, поскольку она не предусмотрена спецификацией JDBC и Java.
  • JDBC V2 требует явной конфигурации. Для аварийного переключения значения по умолчанию не предусмотрены.
    • Протокол должен быть указан в URL. Не выполняется неявное определение протокола по номеру порта.

Изменения конфигурации

Существует только два enum-типа:
  • com.clickhouse.jdbc.DriverProperties - собственные параметры конфигурации драйвера.
  • com.clickhouse.client.api.ClientConfigProperties — свойства конфигурации клиента. Изменения в конфигурации клиента описаны в документации по Java-клиенту.
Свойства подключения разбираются следующим образом:
  • Сначала URL разбирается на свойства. Они имеют приоритет над всеми остальными свойствами.
  • Свойства драйвера не передаются клиенту.
  • Параметры конечной точки (хост, порт, протокол) разбираются из URL.
Пример:

Изменения типов данных

Числовые типы
  • Основное различие заключается в том, что беззнаковые типы сопоставляются с типами Java для лучшей переносимости.
Строковые типы
  • FixedString в обеих версиях читается как есть. Например, FixedString(10) для 'John' будет прочитан как 'John\0\0\0\0\0\0\0\0\0'.
  • При использовании PreparedStatement#setBytes значение преобразуется в unhex('<hex_string>'), а затем считывается как String.
  • Строки хранятся в кодировке UTF-8.
Типы даты/времени
  • Time и Time64 поддерживаются в V2 только в качестве новых типов.
  • DateTime и DateTime64 сопоставляются с java.sql.Timestamp для обеспечения лучшей совместимости с JDBC.
Типы EnumВложенные типы
  • В V2 Array по умолчанию сопоставляется с java.sql.Array для совместимости с JDBC. Это также сделано, чтобы предоставить больше информации о возвращаемом значении массива. Полезно для вывода типов.
  • В V2 Array реализует метод getResultSet(), который возвращает java.sql.ResultSet с тем же содержимым, что и исходный массив.
  • V1 использует STRUCT для Map, но всегда возвращает объект типа java.util.Map. В V2 это исправлено: Map сопоставляется с JAVA_OBJECT.
  • V1 использует STRUCT для Tuple, но всегда возвращает объект типа List<Object>. V2 отображает Tuple как OTHER и по умолчанию возвращает Object[].
  • V2 добавляет com.clickhouse.data.Tuple#Tuple для записи кортежей. Это упрощает определение того, является ли значение кортежем или массивом.
  • PreparedStatement#setBytes и ResultSet#getBytes нельзя использовать с типами коллекций. Эти методы предназначены для работы с двоичными данными.
  • Обычно java.sql.Array используется для записи и чтения значений типа Array. Драйвер JDBC полностью это поддерживает.
  • В V2 Nested сопоставляется с Array и представляется как массив кортежей.
  • V2 частично поддерживает java.sql.Struct, поскольку этот тип очень похож на Array и не поддерживает пары «ключ-значение». Struct можно использовать для записи значений Tuple.
Гео-типыТипы Nullable и LowCardinality
  • Nullable и LowCardinality — специальные типы-обёртки над другими типами.
  • В V2 эти типы не изменяются.
Специальные типы
  • 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(). В дальнейшем это будет изменено.
  • В DatabaseMetaData.getTypeInfo() столбцы LITERAL_PREFIX и LITERAL_SUFFIX теперь возвращают null для типов данных, для которых префиксы и суффиксы не используются (например, для числовых типов). В V1 эти столбцы возвращали ненулевые значения для таких типов. Эти столбцы следует использовать при генерации SQL-запросов, чтобы корректно заключать литеральные значения в кавычки в соответствии с их типом данных.
Последнее изменение 2 июля 2026 г.