JDBC 驱动
clickhouse-jdbc 使用最新的 Java 客户端实现了标准 JDBC 接口。
如果性能或直接访问至关重要,建议直接使用最新的 Java 客户端。
环境要求
- OpenJDK 8 或更高版本
设置
- Maven
- Gradle(Kotlin)
- Gradle
如果您在需要显式将 JAR 添加到 classpath 的应用程序中使用 JDBC 驱动程序,则需要从以下地址下载该 JAR 文件:
- Maven Central,然后将其添加到 classpath 中
- 从版本
0.9.4开始,提供了一个构件:https://mvnrepository.com/artifact/com.clickhouse/clickhouse-jdbc-all - 使用限定符
all即可获取包含所有打包 (shaded) 依赖的 jar 包。
- 从版本
- 或者从官方仓库
配置
驱动程序类: com.clickhouse.jdbc.ClickHouseDriver
com.clickhouse.jdbc.ClickHouseDriver 是新旧 JDBC 实现的外观类,默认使用新的 JDBC 实现。
如需使用旧版 JDBC 实现,可将 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¶m2=value2][#tag1,tag2,...],例如:
jdbc:clickhouse:http://localhost:8123jdbc:clickhouse:https://localhost:8443?ssl=true
关于 URL 语法,需要注意以下几点:
- URL 中 只能 指定一个 endpoint
- 当所使用的协议不是默认的 'HTTP' 时,必须显式指定协议。
- 当使用的端口不是默认端口 8123 时,必须显式指定端口。
- 驱动程序不会根据端口来猜测协议,必须显式指定协议
- 如果已指定协议,则无需设置
ssl参数。
连接属性
主要配置参数在 java client 中定义。它们应按原样传递给驱动程序。驱动程序还有一些自身的属性不属于客户端配置,列举如下。
驱动属性:
| 属性 | 默认值 | 说明 |
|---|---|---|
disable_frameworks_detection | true | 禁用基于 User-Agent 的框架检测 |
jdbc_ignore_unsupported_values | false | 在不影响驱动正常工作的情况下抑制抛出 SQLFeatureNotSupportedException 异常 |
clickhouse.jdbc.v1 | false | 使用旧版 JDBC 实现,而不是新版 JDBC |
default_query_settings | null | 允许在执行查询操作时传递默认查询设置 |
jdbc_resultset_auto_close | true | 在关闭 Statement 时自动关闭 ResultSet |
beta.row_binary_for_simple_insert | false | 使用基于 RowBinary 写入器的 PreparedStatement 实现,只能用于 INSERT INTO ... VALUES 形式的查询。 |
jdbc_resultset_auto_close | true | 在关闭 Statement 时会自动关闭 ResultSet |
jdbc_use_max_result_rows | false | 启用该选项后,可使用服务器属性 max_result_rows 来限制查询返回的行数。启用后会覆盖用户配置的溢出模式。详细信息请参见 JavaDoc。 |
jdbc_sql_parser | JAVACC | 配置使用的 SQL 解析器。可选值为:ANTLR4、ANTLR4_PARAMS_PARSER、JAVACC。 |
remember_last_set_roles | true | 记住此连接上最近设置的角色。 |
配置示例:
其效果等同于以下 JDBC URL:
注意:无需对 JDBC URL 或属性进行 URL 编码,驱动程序会自动完成编码。
客户端标识
有两种方式可以标识发起请求的应用程序:通过连接属性设置 com.clickhouse.client.api.ClientConfigProperties#CLIENT_NAME,或使用 java.sql.Connection#setClientInfo(String name, String value) 方法。
两种方式都会在查询日志中生成以下 http_user_agent 值:
操作标识
JDBC 驱动程序会为每个操作生成一个 query_id (目前该 ID 会出现在服务器异常信息中) 。
要为某个操作设置 log_comment,请使用 com.clickhouse.jdbc.StatementImpl#getLocalSettings 方法。这需要先将 Statement 或 PreparedStatement 强制转换为 com.clickhouse.jdbc.StatementImpl。
注意: 该方法仅适用于在单线程中使用 Statement 的场景,因为 localSettings 会在各线程间共享。
支持的数据类型
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)将返回Int8列对应的Float64值。rs.getLong(1)将返回Int8列对应的Long值。rs.getByte(1)如果值落在Byte可表示的范围内,可以返回Int16列的Byte值。
- 由于存在数据损坏风险,不建议将较宽范围的类型转换为较窄范围的类型。
Bool类型也可以视为数值类型使用。- 所有数值类型都可以读取为
java.lang.String类型。 - 将 Java
Float.MAX_VALUE作为Float存储时会出现问题 (https://github.com/ClickHouse/clickhouse-java/issues/809) 。将相同的值以Double类型存储可以解决该问题。
字符串类型
| ClickHouse 类型 | JDBC 类型 | Java 类 |
|---|---|---|
| String | VARCHAR | java.lang.String |
| FixedString | VARCHAR | java.lang.String |
String只能被读取为java.lang.String或byte[]。FixedString在读取时按原样返回,若长度不足对应列的长度,会在末尾用零字节补齐。 (例如,将'John'定义为FixedString(10)时,读取结果为'John\0\0\0\0\0\0\0\0\0'。)
枚举类型
| ClickHouse 类型 | JDBC 类型 | Java 类 |
|---|---|---|
| Enum8 | OTHER | java.lang.String |
| Enum16 | OTHER | java.lang.String |
Enum8和Enum16默认映射为java.lang.String类型。- 可以通过相应的数值类型专用 getter 方法,或通过
getObject(columnIndex, Integer.class)方法,将枚举值读取为数值类型。 Enum16在内部映射为short类型,而Enum8映射为byte类型。应避免将Enum16以byte形式读取,因为存在数据损坏的风险。- 枚举值可以在
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 |
- 日期/时间类型会被映射为
java.sql类型,以便与 JDBC 有更好的兼容性。不过,仍然可以通过ResultSet#getObject(columnIndex, Class<T>)并将相应的类作为第二个参数传入,来获取java.time.LocalDate、java.time.LocalDateTime、java.time.LocalTime。rs.getObject(1, java.time.LocalDate.class)将返回Date列的java.time.LocalDate值。rs.getObject(1, java.time.LocalDateTime.class)将返回DateTime列的java.time.LocalDateTime值。rs.getObject(1, java.time.LocalTime.class)将返回Time列的java.time.LocalTime值。
Date,Date32,Time,Time64不会受到服务器时区的影响。DateTime、DateTime64会受到服务器或会话时区的影响。DateTime和DateTime64可以通过getObject(colIndex, ZonedDateTime.class)将其读取为ZonedDateTime对象。
嵌套类型
| ClickHouse 类型 | JDBC 类型 | Java 类 |
|---|---|---|
| Array | ARRAY | java.sql.Array |
| Tuple | OTHER | com.clickhouse.data.Tuple |
| Map | JAVA_OBJECT | java.util.Map |
| Nested | ARRAY | java.sql.Array |
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可以通过getObject(columnIndex, Array.class)方法读取为Array类型。此时,Array#baseTypeName将返回该Tuple列的定义。
写入数组
使用 java.sql.Connection#createArrayOf 来实例化 java.sql.Array 对象。该对象旨在统一不同数据库中的数组处理方式。
需要通过 Connection 将配置传递给 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 会映射为 com.clickhouse.data.Tuple 对象,应通过调用 setObject(columnIndex, tuple) 方法,以该对象形式写入。
也可以使用 java.sql.Struct 对象来写入 Tuple,以提高可移植性。
示例
读取 Tuple 类型
方法 getObject(columnIndex) 会返回 Object[]。通过调用 getObject(columnIndex, Array.class) 方法,可以将 Tuple 读取为 java.sql.Array。
示例
写入 Map 类型
只能将 Map 作为 java.collections.Map 对象写入,因为该类型需要键值对 (java.sql.Struct 不支持键值对) 。
示例
读取 Map 类型
可以通过 getObject(columnIndex, Map.class) 方法将 Map 读取为 java.util.Map 对象。
示例
写入嵌套
使用 java.sql.Connection#createStruct 来实例化 java.sql.Struct 对象。此对象旨在在不同数据库之间统一嵌套处理的方式。
需要通过 Connection 将配置信息传递给 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 的更统一方式读取嵌套元素。当嵌套元素的确切类型未知时,这非常有用。
示例
地理类型
| 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实例。- 可以通过
getObject(columnIndex, String.class)方法将UUID作为String类型进行读取/写入。 IPv4和IPv6不是 JDBC 标准类型,但它们是 JDK 的一部分。默认情况下,调用getObject()方法时会返回java.net.Inet4Address和java.net.Inet6Address实例。IPv4和IPv6可以通过getObject(columnIndex, String.class)方法以String形式读取/写入。
处理日期、时间和时区
请阅读 日期/时间指南,该指南解释了驱动程序在处理日期/时间和时间戳时的常见陷阱与逻辑。
创建连接
提供凭据和配置
简单语句
插入
HikariCP
更多信息
如需了解更多信息,请参阅我们的 GitHub 仓库 和 Java 客户端文档。
故障排除
日志
该驱动使用 slf4j 进行日志记录,并会选用 classpath 中首个可用的实现。
解决大批量插入时的 JDBC 超时问题
在 ClickHouse 中执行耗时较长的大批量插入操作时,可能会遇到如下 JDBC 超时错误:
这些错误可能会中断数据插入过程并影响系统稳定性。为解决该问题,您可能需要在客户端操作系统中调整一些超时设置。
Mac OS
在 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 上,仅调整等效设置可能仍无法解决问题。由于 Linux 处理套接字 keep-alive 设置的方式有所不同,因此还需要执行额外步骤。请按以下步骤操作:
- 在
/etc/sysctl.conf或其他相关的配置文件中调整以下 Linux 内核参数:
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 Client 文档。
连接属性按以下方式解析:
- 首先从 URL 中解析属性。这些属性将优先生效,并覆盖所有其他属性。
- 驱动属性不会传递给客户端。
- 端点 (主机、端口和协议) 从 URL 中解析得到。
Example:
数据类型变更
数值类型
| 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在两个版本中均按原样读取。例如,将'John'定义为FixedString(10)时,读取结果为'John\0\0\0\0\0\0\0\0\0'。- 当使用
PreparedStatement#setBytes时,其值会被转换为unhex('<hex_string>'),然后再按String读取。 - 字符串以 UTF-8 编码存储。
日期和时间类型
| 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 的兼容性。
枚举类型
| 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 |
| Nested | ❌ | ARRAY | java.sql.Array | STRUCT | java.sql.Struct |
- 在 V2 中,
Array默认会映射为java.sql.Array,以确保与 JDBC 的兼容性。这也能够提供关于返回数组值的更多信息,有助于进行类型推断。 - 在 V2 中,
Array实现了getResultSet()方法,用于返回一个与原始数组内容相同的java.sql.ResultSet对象。 - V1 对
Map使用STRUCT,但始终返回java.util.Map对象。V2 通过将Map映射为JAVA_OBJECT解决了这一问题。 - V1 使用
STRUCT作为Tuple的 JDBC 类型,但始终返回List<Object>对象。V2 将Tuple映射为OTHER,默认返回Object[]。 - V2 引入了
com.clickhouse.data.Tuple#Tuple,用于写入 Tuple,从而简化判断某个值是 Tuple 还是数组。 PreparedStatement#setBytes和ResultSet#getBytes不能与集合类型一起使用。这些方法是为处理二进制字符串而设计的。- 通常使用
java.sql.Array来写入和读取 Array 类型。JDBC 驱动对此提供了完整支持。 - 在 V2 中,
Nested被映射为Array,并将其表示为元组数组。 - V2 对
java.sql.Struct提供了部分支持,因为它与 Array 类型非常相似,而且不支持键值对。Struct可用于写入Tuple类型的值。
地理空间类型
| 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.lang.Object | 不支持 | 不支持 |
| Variant | ❌ | OTHER | java.lang.Object | 不支持 | 不支持 |
- V1 使用
VARCHAR作为UUID的 JDBC 类型,但始终返回java.util.UUID对象。V2 通过将UUID映射为OTHER,并仍然返回java.util.UUID对象来修复此问题。 - V1 对
IPv4和IPv6使用VARCHAR,但始终返回java.net.Inet4Address和java.net.Inet6Address对象。V2 通过将IPv4和IPv6映射为 JDBC 类型OTHER来修复这一问题,并返回java.net.Inet4Address和java.net.Inet6Address对象。 Dynamic和Variant是 V2 中引入的新类型,在 V1 中不受支持。JSON基于Dynamic类型,因此仅在 V2 中可用。- IPv4 和 IPv6 值可以通过
getBytes(columnIndex)方法读取为byte[]。不过,建议为这些类型使用专门的类。 - V2 不支持将 IP 地址读取为数值类型,因为这类转换更适合由 InetAddress 类来完成。
数据库元数据变更
- V2 仅使用
Schema这一术语来表示数据库,Catalog术语保留作今后使用。 - V2 对
DatabaseMetaData.supportsTransactions()和DatabaseMetaData.supportsSavepoints()返回false。这一行为将在后续版本中进行调整。