JDBC 驱动
clickhouse-jdbc 使用最新的 Java 客户端实现了标准 JDBC 接口。
如果性能或直接访问至关重要,建议直接使用最新的 Java 客户端。
环境要求
- OpenJDK 8 或更高版本
设置
- Maven
- Gradle(Kotlin)
- Gradle
如果您在应用程序中使用 JDBC 驱动程序,且该应用程序需要将 jar 添加到 classpath,则需要从以下地址下载 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。
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 中只能包含一个 endpoint
- 当使用的协议不是默认的 HTTP 协议时,应显式指定协议
- 如果端口不是默认的 '8123',则必须显式指定。
- 驱动程序不会根据端口来推断协议,你需要显式指定协议
- 如果已指定协议,则无需设置
ssl参数。
连接属性
主要配置参数在 java client 中定义。这些参数应按原样传递给驱动程序。驱动程序还有一些自有属性,它们不属于客户端配置的一部分,具体列举如下。
驱动属性:
| 属性 | 默认值 | 描述 |
|---|---|---|
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 | 在关闭 Statement 时自动关闭 ResultSet |
beta.row_binary_for_simple_insert | false | 使用基于 RowBinary writer 的 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。 |
配置示例:
这等同于以下 JDBC URL:
注意:无需对 JDBC URL 或属性进行 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)将返回Int8列的Float64值。rs.getLong(1)将返回Int8列的Long值。- 如果值在
Byte的取值范围内,rs.getByte(1)可以返回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在读取时会保持原样,并在末尾用零字节补齐到该列的长度。(例如,将'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 类型
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.collections.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)方法以String形式对UUID进行读写。 IPv4和IPv6不是 JDBC 标准类型,但它们是 JDK 的一部分。默认情况下,调用getObject()方法时会返回java.net.Inet4Address和java.net.Inet6Address实例。- 通过
getObject(columnIndex, String.class)方法,IPv4和IPv6可以以String形式进行读写。
处理日期、时间和时区
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 超时错误:
这些错误可能会中断数据插入过程并影响系统稳定性。为解决该问题,可能需要在客户端操作系统中调整若干超时设置。
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 中解析而来。
示例:
数据类型变更
数值类型
| 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 将
Tuple映射为STRUCT,但始终返回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 中受支持。- 可以通过
getBytes(columnIndex)方法将 IPv4 和 IPv6 的值读取为byte[]。不过,建议针对这些类型使用专门的类。 - V2 不支持以数值形式读取 IP 地址,因为在 InetAddress 类中完成该转换的实现更为合理。
数据库元数据变更
- V2 仅使用
Schema一词来表示数据库。Catalog一词保留供将来使用。 - V2 会在
DatabaseMetaData.supportsTransactions()和DatabaseMetaData.supportsSavepoints()中返回false。这一行为将在后续版本的开发中进行调整。