KingbaseES JDBC 深度实战指南(上):从驱动选型到连接管理,夯实国产数据库交互基础
《KingbaseES数据库》本篇文章所属专栏—持续更新中—欢迎订阅!
引言
在国产数据库蓬勃发展的当下,KingbaseES 作为企业级关系型数据库的代表,已广泛应用于金融、政务、能源等关键领域。而 JDBC(Java Database Connectivity)作为 Java 生态连接数据库的 “黄金桥梁”,其在 KingbaseES 中的正确使用,直接决定了 Java 应用与数据库交互的效率、安全性与稳定性。
然而,许多开发者在使用 KingbaseES JDBC 时,常面临 “参数配置混乱”“大对象处理踩坑”“高可用方案落地难” 等问题 —— 明明遵循了基础流程,却因不了解驱动特性导致性能瓶颈;想实现读写分离减轻主库压力,却因参数配置不当引发数据一致性问题;处理 BLOB/CLOB 大对象时,又因兼容模式差异导致数据丢失…… 这些问题的根源,往往是对 KingbaseES JDBC 的核心特性、接口设计与实战细节缺乏系统认知。
下面我将基于官方文档,拒绝 “泛泛而谈”,聚焦 “实战落地”:从驱动包选型、连接建立的底层逻辑,到语句对象的性能优化技巧;从大对象处理的兼容模式差异,到事务管理与元数据应用的深度细节;再到读写分离、高可用配置的完整方案,每一个知识点均对应文档中的核心定义,每一段代码均源自官方示例的优化延伸。
无论是刚接触 KingbaseES 的新手,还是需要解决复杂场景的资深开发者,都能通过本文掌握 Java 与 KingbaseES 高效交互的 “底层逻辑” 与 “实战技巧”,真正解锁国产数据库与 Java 生态融合的核心能力。
一、JDBC 与 KingbaseES JDBC 概述
1.1 JDBC 简介
JDBC 是 Java 语言中用于连接和操作关系型数据库的标准 API,它基于 X/Open SQL 调用级接口(CLI)制定,为开发者提供了一套统一的接口来访问不同厂商的数据库。JDBC 4.0 版本符合 SQL 2003 标准,通过java.sql
和javax.sql
两个核心包,定义了包括驱动程序、连接、语句、结果集等在内的一系列接口和类,数据库厂商只需实现这些接口,就能为 Java 应用提供数据库连接服务。
简单来说,JDBC 就像是一座 “桥梁”,一边连接着 Java 应用程序,另一边连接着各种关系型数据库,让 Java 代码能够轻松地与数据库进行数据交互,比如执行 SQL 语句、获取查询结果等。
1.2 KingbaseES JDBC 简介
KingbaseES JDBC 提供了名为kingbase8jdbc
的 JDBC 驱动程序,它全面支持 SUN JDBC 3.0 标准,并部分支持 JDBC 4.0 API 标准。通过 KingbaseES JDBC 提供的接口对象,Java 应用程序可以完成与 KingbaseES 数据库的连接建立、SQL 语句执行、结果获取、事务管理以及连接关闭等一系列操作。
KingbaseES JDBC 主要实现了 JDBC 标准中的多个核心接口,这些接口涵盖了数据库交互的各个关键环节,具体如下表所示:
接口类别 | 具体接口 | 主要功能 |
---|---|---|
驱动与连接相关 | java.sql.Driver | 用于注册驱动并创建数据库连接 |
java.sql.Connection | 代表与数据库的连接,用于创建语句对象、管理事务等 | |
javax.sql.DataSource | 提供另一种获取数据库连接的方式,支持连接池等特性 | |
语句对象相关 | java.sql.Statement | 用于执行简单的 SQL 语句(无参数) |
java.sql.PreparedStatement | 用于执行预编译的 SQL 语句(支持参数化查询) | |
java.sql.CallableStatement | 用于调用数据库中的存储过程 | |
结果集相关 | java.sql.ResultSet | 存储 SQL 查询返回的结果数据,支持数据读取和更新 |
java.sql.ResultSetMetaData | 提供结果集的元数据信息,如列名、列类型等 | |
大对象相关 | java.sql.Blob | 用于处理二进制大对象数据(如图片、音频等) |
java.sql.Clob | 用于处理字符大对象数据(如大文本) | |
java.sql.SQLXML | 用于处理 XML 类型的数据 | |
事务相关 | java.sql.Savepoint | 用于在事务中设置保存点,支持部分回滚 |
元数据相关 | java.sql.DatabaseMetaData | 提供数据库的元数据信息,如数据库版本、支持的功能等 |
java.sql.ParameterMetaData | 提供 PreparedStatement 参数的元数据信息,如参数类型、数量等 |
KingbaseES JDBC 驱动的体系结构如下图所示,清晰地展示了 Java 应用通过 JDBC 驱动与 KingbaseES 数据库之间的交互流程:
从上图可以看出,Java 应用程序首先通过 KingbaseES JDBC Driver 发起数据库操作请求,驱动程序通过 Java Sockets 与 Kingbase 数据库建立通信连接,然后将 SQL 语句传递给数据库的 SQL Engine 或 PL/SQL Engine 进行执行,最终将执行结果通过驱动程序返回给 Java 应用程序。
目前,KingbaseES JDBC 驱动kingbase8jdbc
支持在 JDK 1.6 及以上版本的平台上运行,能够满足不同 Java 项目的开发需求。
1.3 KingbaseES JDBC 操作流程
使用 KingbaseES JDBC 在客户端访问和操纵 KingbaseES 数据库中的数据,通常遵循以下固定的操作流程,这一流程确保了数据交互的规范性和高效性:
- 建立与数据库的连接:这是所有数据库操作的前提,需要通过指定数据库的 URL、用户名和密码等信息,借助 DriverManager 或 DataSource 方式创建与数据库的连接。
- 创建语句对象:根据 SQL 语句的类型和需求,创建对应的 Statement、PreparedStatement 或 CallableStatement 对象,用于发送 SQL 语句到数据库。
- 执行查询并返回结果集对象:通过语句对象执行 SQL 查询语句,获取包含查询结果的数据集合,即 ResultSet 对象。
- 处理结果集对象:遍历 ResultSet 对象,读取其中的数据并进行相应的业务处理,如数据展示、数据计算等;如果是更新操作(如 INSERT、UPDATE、DELETE),则获取更新的行数等执行结果。
- 关闭结果集和语句对象:在完成结果集处理后,及时关闭 ResultSet 和 Statement 对象,释放相关的 JDBC 资源,避免资源泄漏。
- 关闭与数据库的连接:在所有数据库操作完成后,关闭与数据库的连接,释放数据库连接资源,提高数据库的并发处理能力。
下面通过一个简单的流程图,直观地展示这一操作流程:
二、KingbaseES JDBC 驱动包与版本信息
2.1 JDBC 驱动包选择
为了确保 Java 应用能够正常连接和操作 KingbaseES 数据库,需要选择合适的 JDBC 驱动包。KingbaseES 提供了不同版本的 JDBC 驱动包,分别对应不同的 JDK 最低支持版本,开发者可以根据项目所使用的 JDK 版本进行选择,具体如下表所示:
驱动包名称 | 支持最低 JDK 版本 | 适用场景 |
---|---|---|
kingbase8-9.0.0.jre6.jar | JDK 1.6 | 适用于使用 JDK 1.6 版本开发的 Java 项目 |
kingbase8-9.0.0.jre7.jar | JDK 1.7 | 适用于使用 JDK 1.7 版本开发的 Java 项目 |
kingbase8-9.0.0.jar | JDK 1.8 | 适用于使用 JDK 1.8 及以上版本开发的 Java 项目 |
这些 JDBC 驱动程序默认存放在 KingbaseES 数据库安装程序目录的 JDBC 文件夹内。在实际项目中,如果需要将现有 Oracle 数据库的 JDBC 驱动替换为 KingbaseES 的 JDBC 驱动,只需将 Oracle 的 JDBC 驱动程序文件替换为上述对应的 KingbaseES JDBC 驱动包,并修改数据库连接字符串即可,极大地降低了项目迁移的成本。
2.2 Maven 项目依赖配置
在 Maven 项目中,不需要手动下载和导入 JDBC 驱动包,只需在项目的pom.xml
文件中添加相应的依赖配置,Maven 会自动从中央仓库下载并管理驱动包。根据项目所使用的 JDK 版本,可选择以下对应的依赖配置:
2.2.1 支持 JDK 1.8 及以上版本
<!-- 最低可支持JDK1.8 -->
<dependency><groupId>cn.com.kingbase</groupId><artifactId>kingbase8</artifactId><version>9.0.0</version>
</dependency>
2.2.2 支持 JDK 1.7 版本
<!-- 最低可支持JDK1.7 -->
<dependency><groupId>cn.com.kingbase</groupId><artifactId>kingbase8</artifactId><version>9.0.0.jre7</version>
</dependency>
2.2.3 支持 JDK 1.6 版本
<!-- 最低可支持JDK1.6 -->
<dependency><groupId>cn.com.kingbase</groupId><artifactId>kingbase8</artifactId><version>9.0.0.jre6</version>
</dependency>
2.2.4 国密算法依赖(可选)
如果项目中需要使用 sm3、scram - sm3 或者 sm4 等国密算法进行数据加密和身份认证,还需要在pom.xml
文件中额外添加如下依赖,以提供国密算法支持:
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk18on -->
<dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk18on</artifactId><version>1.80</version>
</dependency>
2.3 获取 KingbaseES JDBC Driver 版本信息
在开发和维护过程中,有时需要获取 KingbaseES JDBC Driver 的版本信息,以便确认驱动版本是否符合项目需求或排查版本兼容性问题。KingbaseES 提供了三种获取 JDBC 驱动版本信息的方法,以下以kingbase8-9.0.0.jar
驱动包为例进行介绍:
2.3.1 直接查看相关文件
首先找到$KINGBASE_HOME/Interface/jdbc/kingbase8-9.0.0.jar
文件(其中$KINGBASE_HOME
为 KingbaseES 的安装路径),然后使用压缩软件(如 WinRAR、7 - Zip 等)打开该 JAR 包,进入META-INF
目录,找到MANIFEST.MF
文件并打开。在该文件中,通常会包含 JDBC 驱动的版本信息,如Implementation-Version
等字段所对应的值,通过这些字段即可获取驱动的版本信息。
2.3.2 利用命令行方式
打开操作系统的命令行终端(Windows 系统为命令提示符或 PowerShell,Linux 系统为终端),进入到$KINGBASE_HOME/Interface/jdbc
目录下,然后执行以下命令:
java -jar kingbase8-9.0.0.jar -v
执行该命令后,命令行终端会输出 KingbaseES JDBC Driver 的版本信息,包括版本号、构建时间等详细内容,开发者可以直接从输出结果中获取所需的版本信息。
2.3.3 利用 Java 程序
通过编写 Java 程序,调用java.sql.DatabaseMetaData
接口中的getDriverVersion()
方法,也可以获取 KingbaseES JDBC Driver 的版本信息。以下是完整的 Java 程序示例:
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.SQLException;public class GetJdbcDriverVersion {public static void main(String[] args) {// 数据库连接信息String url = "jdbc:kingbase8://localhost:54321/testdb"; // 数据库URL,testdb为数据库名String user = "system"; // 数据库用户名String password = "manager"; // 数据库密码Connection conn = null;try {// 加载JDBC驱动Class.forName("com.kingbase8.Driver");// 建立数据库连接conn = DriverManager.getConnection(url, user, password);// 获取数据库元数据DatabaseMetaData metaData = conn.getMetaData();// 获取JDBC驱动版本信息String driverVersion = metaData.getDriverVersion();System.out.println("KingbaseES JDBC Driver Version: " + driverVersion);} catch (ClassNotFoundException e) {System.out.println("加载JDBC驱动失败:" + e.getMessage());} catch (SQLException e) {System.out.println("数据库操作异常:" + e.getMessage());} finally {// 关闭数据库连接if (conn != null) {try {conn.close();} catch (SQLException e) {System.out.println("关闭数据库连接失败:" + e.getMessage());}}}}
}
在上述代码中,首先通过Class.forName("com.kingbase8.Driver")
加载 KingbaseES JDBC 驱动,然后使用DriverManager.getConnection()
方法建立与数据库的连接,接着通过Connection
对象的getMetaData()
方法获取DatabaseMetaData
对象,最后调用getDriverVersion()
方法获取并打印 JDBC 驱动的版本信息。运行该程序,即可在控制台输出 KingbaseES JDBC Driver 的版本信息。
三、JDBC 建立与关闭数据库连接
建立与数据库的连接是进行所有数据库操作的基础,KingbaseES JDBC 提供了两种常用的建立数据库连接的方法:通过DriverManager
和通过DataSource
。同时,在完成数据库操作后,及时关闭连接以释放资源也至关重要。
3.1 使用 DriverManager 建立连接
DriverManager
是 JDBC 中的一个重要类,它负责管理已注册的 JDBC 驱动程序,并根据数据库 URL 找到合适的驱动程序来建立与数据库的连接。
3.1.1 加载 JDBC 驱动
在使用DriverManager
建立数据库连接之前,需要先加载 KingbaseES 的 JDBC 驱动。有两种常见的加载方式:
- 使用
Class.forName()
方法:
try {Class.forName("com.kingbase8.Driver");
} catch (ClassNotFoundException e) {e.printStackTrace();// 处理驱动加载失败的情况,如提示用户检查驱动包是否正确导入等
}
这种方法通过反射机制加载驱动类,当加载com.kingbase8.Driver
类时,该类会在静态代码块中自动向DriverManager
注册自身,从而完成驱动的注册。
- 使用
DriverManager.registerDriver()
方法:
try {DriverManager.registerDriver(new com.kingbase8.Driver());
} catch (SQLException e) {e.printStackTrace();// 处理驱动注册失败的情况
}
这种方法直接创建com.kingbase8.Driver
对象,并将其注册到DriverManager
中。
在实际开发中,推荐使用第一种方法(Class.forName()
)来加载驱动,因为它更加灵活,且避免了直接依赖驱动类的具体实现。
3.1.2 建立数据库连接
加载驱动后,就可以通过DriverManager.getConnection()
方法建立与 KingbaseES 数据库的连接。该方法提供了三种重载形式,以适应不同的参数传递方式:
getConnection(String url, String user, String password)
:直接传递数据库 URL、用户名和密码。
String url = "jdbc:kingbase8://localhost:54321/testdb"; // 数据库URL
String user = "system"; // 用户名
String password = "manager"; // 密码
try {Connection conn = DriverManager.getConnection(url, user, password);// 连接建立成功,后续可进行数据库操作
} catch (SQLException e) {e.printStackTrace();// 处理连接建立失败的情况,如检查URL、用户名、密码是否正确,数据库服务是否正常运行等
}
getConnection(String url, java.util.Properties info)
:通过Properties
对象传递连接属性,包括用户名、密码等。
String url = "jdbc:kingbase8://localhost:54321/testdb";
Properties info = new Properties();
info.put("user", "system"); // 设置用户名
info.put("password", "manager"); // 设置密码
try {Connection conn = DriverManager.getConnection(url, info);// 连接建立成功
} catch (SQLException e) {e.printStackTrace();
}
这种方式适用于需要传递较多连接属性的场景,除了用户名和密码,还可以设置其他连接参数,如字符编码、事务隔离级别等。
getConnection(String url)
:将用户名和密码包含在 URL 中传递。
String url = "jdbc:kingbase8://localhost:54321/testdb?user=system&password=manager";
try {Connection conn = DriverManager.getConnection(url);// 连接建立成功
} catch (SQLException e) {e.printStackTrace();
}
这种方式将连接参数直接拼接在 URL 中,虽然使用简单,但安全性较低,不推荐在生产环境中使用,尤其是当密码包含特殊字符时,可能会导致 URL 解析错误。
3.1.3 数据库 URL 格式
KingbaseES JDBC 支持多种数据库 URL 格式,以适应不同的网络环境和配置需求,具体格式如下:
-
jdbc:kingbase8:database
:这种格式适用于数据库服务器与客户端在同一台机器上(即localhost
),且使用默认端口号(KingbaseES 服务器的默认端口号为 54321)的情况,其中database
为数据库名。例如:jdbc:kingbase8:testdb
,表示连接本地默认端口上的testdb
数据库。 -
jdbc:kingbase8://host/database
:指定数据库服务器的主机名(或 IP 地址)host
和数据库名database
,使用默认端口号。例如:jdbc:kingbase8://192.168.1.100/testdb
,表示连接192.168.1.100
主机上默认端口的testdb
数据库。 -
jdbc:kingbase8://host:port/database
:指定数据库服务器的主机名host
、端口号port
和数据库名database
。这是最常用的格式,能够精确地定位到目标数据库。例如:jdbc:kingbase8://192.168.1.100:54322/testdb
,表示连接192.168.1.100
主机上54322
端口的testdb
数据库。 -
jdbc:kingbase8://host:port/database?para1=val1¶2=val2…
:在基本 URL 的基础上,通过查询参数的形式设置额外的连接属性,如字符编码、超时时间等。例如:jdbc:kingbase8://localhost:54321/testdb?clientEncoding=UTF-8&loginTimeout=10
,表示连接本地54321
端口的testdb
数据库,设置客户端编码为UTF-8
,登录超时时间为 10 秒。
如果数据库服务器的主机地址是 IPv6 地址,则必须用中括号将地址括起来,格式如下:jdbc:kingbase8://[IPv6host]:port/database?para1=val1¶2=val2…
例如:jdbc:kingbase8://[2021:0:0:0:0:0:0:50]:54321/testdb
。需要注意的是,如果使用了 Socks 代理,此处 IPv6 地址需要使用冒分十六进制表示法(如上述示例),不能使用 0 位压缩表示法(如2021::50
)。
3.1.4 处理 URL 中的特殊字符
当数据库连接 URL 中包含%
、?
、&
、/
等特殊字符时,会对 JDBC 解析连接串造成影响,导致连接失败。为了解决这个问题,可以采用以下三种方法:
- 使用
Properties
对象:将连接属性(如用户名、密码、数据库名等)存储在Properties
容器中,然后调用getConnection(String url, Properties props)
方法建立连接。使用这种方法,连接属性中的特殊字符不需要做任何处理。但需要注意的是,数据库名称必须存储在 URL 中,所以这种方法不能处理数据库名称中含有特殊字符的情况。
示例代码:
String url = "jdbc:kingbase8://localhost:54321/testdb"; // 数据库名testdb无特殊字符
Properties props = new Properties();
props.put("user", "user%name"); // 用户名包含特殊字符%
props.put("password", "pass?word"); // 密码包含特殊字符?
try {Connection conn = DriverManager.getConnection(url, props);// 连接建立成功
} catch (SQLException e) {e.printStackTrace();
}
- 使用转义字符处理过的 URL:URL 的词法规则要求一些特殊字符必须经过转义才能被正确识别。KingbaseES JDBC 使用
URLEncoder.encode(String arg1, System.getProperty("file.encoding"))
方法对特殊字符进行转义,其中arg1
为待转义的连接属性值。
URLEncoder
的转义规则如下:
- 字母数字字符(
a
到z
、A
到Z
和0
到9
)保持不变。 - 特殊字符
.
、-
、*
和_
保持不变。 - 空格字符转换为一个加号
+
。 - 所有其他字符都是不安全的,首先使用相应平台的默认编码机制将它们转换为一个或多个字节,然后每个字节用一个包含 3 个字符的字符串
%xy
表示,其中xy
为该字节的两位十六进制表示形式。
示例代码:
import java.net.URLEncoder;public class UrlEscapeExample {public static void main(String[] args) throws Exception {String user = "user%name";String password = "pass?word";// 对用户名和密码进行转义String encodedUser = URLEncoder.encode(user, System.getProperty("file.encoding"));String encodedPassword = URLEncoder.encode(password, System.getProperty("file.encoding"));// 构建转义后的URLString url = "jdbc:kingbase8://localhost:54321/testdb?user=" + encodedUser + "&password=" + encodedPassword;try {Connection conn = DriverManager.getConnection(url);// 连接建立成功} catch (SQLException e) {e.printStackTrace();}}
}
- 使用配置文件(适用于连接参数较多的场景):当连接参数较多时,可以将连接参数配置在一个配置文件中,然后在连接串中通过
ConfigurePath
参数指定配置文件的路径。这种方法可以避免在 URL 中直接拼接大量参数,同时也能处理参数中的特殊字符。
示例:
- 配置文件
jdbc.conf
内容:
plaintext
user=user%name
password=pass?word
clientEncoding=UTF-8
- 连接 URL:
jdbc:kingbase8://localhost:54321/testdb?ConfigurePath=jdbc.conf
- 建立连接的代码:
String url = "jdbc:kingbase8://localhost:54321/testdb?ConfigurePath=jdbc.conf";
try {Connection conn = DriverManager.getConnection(url);// 连接建立成功
} catch (SQLException e) {e.printStackTrace();
}
3.2 使用 DataSource 建立连接
DataSource
接口是 JDBC 3.0 规范中定义的另一种获取数据库连接的方法,它相比DriverManager
具有更多的优势,如支持连接池、分布式事务等特性,同时提高了应用程序的可移植性。
使用DataSource
进行数据库连接时,应用程序通过一个逻辑名称(如 JNDI 名称)获取DataSource
对象,该对象由应用服务器或连接池管理工具创建和配置,包含了数据库连接的相关信息。如果数据源的信息(如数据库地址、端口号等)发生变化,只需修改DataSource
对象的配置,而不需要修改应用程序代码,极大地简化了应用程序的维护工作。
DataSource
接口的实现可以分为两种:基本实现和支持连接池的实现。在基本实现中,每个Connection
对象对应一个物理的数据库连接,当关闭Connection
对象时,物理连接也会随之关闭;而在支持连接池的实现中,DataSource
会维护一个连接池,Connection
对象关闭后会被放回连接池,供其他应用程序复用,从而提高数据库的访问效率。
KingbaseES JDBC 在KBSimpleDataSource
类中实现了基本的DataSource
接口,在Jdbc3PoolingDataSource
类中实现了具有连接池功能的DataSource
接口。下面分别介绍它们的使用方法。
3.2.1 使用 KBSimpleDataSource(不使用连接池)
使用KBSimpleDataSource
建立数据库连接的步骤如下:
- 创建 KBSimpleDataSource 对象:
KBSimpleDataSource ds = new KBSimpleDataSource();
- 初始化连接属性:
KBSimpleDataSource
提供了一系列setXXX()
方法用于设置数据库连接的属性,包括数据库名、密码、端口号、服务器地址、用户名等标准属性。
ds.setDatabaseName("testdb"); // 设置数据库名
ds.setPassword("manager"); // 设置密码
ds.setPortNumber(54321); // 设置端口号
ds.setServerName("localhost"); // 设置服务器地址(主机名或IP)
ds.setUser("system"); // 设置用户名
- 获取数据库连接:通过
getConnection()
方法获取数据库连接,该方法有两种重载形式:
getConnection()
:如果已经通过setUser()
和setPassword()
方法设置了用户名和密码,可直接调用此方法获取连接。
try {Connection conn = ds.getConnection();// 连接建立成功,进行数据库操作
} catch (SQLException e) {e.printStackTrace();
}
getConnection(String user, String password)
:如果没有提前设置用户名和密码,或需要使用不同的用户身份连接数据库,可调用此方法并传递用户名和密码。
try {Connection conn = ds.getConnection("system", "manager");// 连接建立成功
} catch (SQLException e) {e.printStackTrace();
}
3.2.2 使用 Jdbc3PoolingDataSource(使用连接池)
Jdbc3PoolingDataSource
是支持连接池功能的DataSource
实现类,使用它可以提高数据库连接的复用率,减少连接建立和关闭的开销,从而提高应用程序的性能。
使用Jdbc3PoolingDataSource
建立数据库连接的步骤如下:
- 创建 Jdbc3PoolingDataSource 对象:
Jdbc3PoolingDataSource ds = new Jdbc3PoolingDataSource();
- 设置连接池和数据库连接属性:除了设置数据库连接的基本属性(如数据库名、用户名、密码等)外,还需要设置连接池的相关属性,如最大连接数、初始连接数等。
// 设置数据源名称(可选,用于标识数据源)
ds.setDataSourceName("A Data Source");
// 设置数据库名
ds.setDatabaseName("testdb");
// 设置用户名
ds.setUser("system");
// 设置密码
ds.setPassword("manager");
// 设置最大连接数,即连接池中最多可容纳的连接数量
ds.setMaxConnections(10);
// 设置初始连接数,即连接池初始化时创建的连接数量
ds.setInitialConnections(10);
// 设置数据库服务器端口号
ds.setPortNumber(54321);
// 设置数据库服务器地址
ds.setServerName("localhost");
- 获取数据库连接:与
KBSimpleDataSource
类似,通过getConnection()
方法获取连接。
try {Connection conn = ds.getConnection();// 进行数据库操作,如创建Statement对象、执行SQL语句等Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("SELECT * FROM table1");// 处理结果集while (rs.next()) {// 读取数据System.out.println(rs.getString(1));}// 关闭结果集、语句对象和连接(连接关闭后会放回连接池)rs.close();stmt.close();conn.close();
} catch (SQLException e) {e.printStackTrace();
}
- 关闭连接池:在应用程序退出或不再需要连接池时,应关闭连接池,释放所有连接资源。
ds.close();
需要注意的是,连接池只需创建一次,通常在应用程序初始化时创建;在应用程序退出时,再执行关闭连接池的操作,以确保资源的正确释放。
3.2.3 使用 DataSource 结合 JNDI
在 J2EE 应用中,通常会使用 JNDI(Java Naming and Directory Interface)来管理DataSource
对象,使得应用程序可以通过逻辑名称查找DataSource
,而不需要硬编码数据库连接信息,提高了应用程序的灵活性和可维护性。
使用DataSource
结合 JNDI 建立数据库连接的步骤如下:
- 建立数据源并绑定到 JNDI:
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.util.Hashtable;
import com.kingbase8.ds.KBSimpleDataSource;public class JndiDataSourceBinding {public static void main(String[] args) {try {// 创建KBSimpleDataSource对象并设置连接属性KBSimpleDataSource ds = new KBSimpleDataSource();ds.setDatabaseName("testdb");ds.setUser("system");ds.setPassword("manager");ds.setPortNumber(54321);ds.setServerName("localhost");// 配置JNDI环境Hashtable<String, String> env = new Hashtable<>();// 设置JNDI初始化上下文工厂env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");// 设置JNDI提供者URL(需要在本地创建对应的目录,如D:/job/jndi)env.put(Context.PROVIDER_URL, "file:/D:/job/jndi");// 创建InitialContext对象Context ctx = new InitialContext(env);// 将DataSource对象绑定到JNDI,绑定名称为"DataSource"ctx.rebind("DataSource", ds);System.out.println("DataSource绑定到JNDI成功!");} catch (NamingException e) {e.printStackTrace();}}
}
在运行上述代码之前,需要先从http://java.sun.com
下载fscontext.jar
和providerutil.jar
两个 JAR 文件,并添加到项目的类路径中,因为com.sun.jndi.fscontext.RefFSContextFactory
类位于这两个 JAR 文件中。
- 通过 JNDI 查找 DataSource 并获取连接:
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Hashtable;public class JndiDataSourceLookup {public static void main(String[] args) {try {// 配置JNDI环境(与绑定数据源时的环境配置一致)Hashtable<String, String> env = new Hashtable<>();env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");env.put(Context.PROVIDER_URL, "file:/D:/job/jndi");// 创建InitialContext对象Context ctx = new InitialContext(env);// 通过JNDI名称查找DataSource对象DataSource ds = (DataSource) ctx.lookup("DataSource");// 获取数据库连接Connection conn = ds.getConnection();// 执行SQL查询Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("SELECT * FROM table1");// 处理结果集while (rs.next()) {System.out.println("ID: " + rs.getInt("id") + ", Name: " + rs.getString("name"));}// 关闭资源rs.close();stmt.close();conn.close();ctx.close();} catch (NamingException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}}
}
通过 JNDI 管理DataSource
,使得应用程序可以在不修改代码的情况下,灵活地切换数据源或修改数据库连接配置,非常适合在大型企业级应用中使用。
3.3 关闭数据库连接
在完成所有数据库操作后,必须及时关闭数据库连接,以释放数据库资源,避免资源泄漏,提高数据库的并发处理能力。关闭数据库连接非常简单,只需调用Connection
对象的close()
方法即可:
if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();// 处理关闭连接失败的情况,如记录日志等}
}
需要注意的是,在关闭连接之前,应先关闭通过该连接创建的ResultSet
和Statement
(或PreparedStatement
、CallableStatement
)对象,以确保所有相关资源都能被正确释放。通常的资源关闭顺序为:先关闭ResultSet
,再关闭Statement
,最后关闭Connection
。
示例代码:
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;try {// 建立连接、创建语句对象、执行查询并处理结果集conn = DriverManager.getConnection(url, user, password);stmt = conn.createStatement();rs = stmt.executeQuery("SELECT * FROM table1");while (rs.next()) {// 处理数据}
} catch (SQLException e) {e.printStackTrace();
} finally {// 关闭结果集if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}// 关闭语句对象if (stmt != null) {try {stmt.close();} catch (SQLException e) {e.printStackTrace();}}// 关闭连接if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}
}
在 Java 7 及以上版本中,可以使用 try-with-resources 语句来自动关闭资源,无需手动调用close()
方法,简化了代码的编写,同时也能确保资源的正确释放。示例代码如下:
try (Connection conn = DriverManager.getConnection(url, user, password);Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("SELECT * FROM table1")) {// 处理结果集while (rs.next()) {// 读取数据}
} catch (SQLException e) {e.printStackTrace();
}
在 try-with-resources 语句中,Connection
、Statement
和ResultSet
对象会在 try 块执行结束后(无论正常结束还是抛出异常)自动关闭,遵循 “声明的顺序相反” 的关闭顺序,即先关闭ResultSet
,再关闭Statement
,最后关闭Connection
。
总结
本篇文章聚焦 “基础能力夯实”,系统讲解了三大核心内容:
- JDBC 与 KingbaseES JDBC 概述:明确 JDBC 的标准定位与 KingbaseES JDBC 的接口体系,结合数据库架构图,厘清 Java 应用与 KingbaseES 的交互逻辑;
- 驱动包与版本信息:详细说明驱动包的选型规则(按 JDK 版本匹配)、Maven 依赖配置、版本信息获取方法,避免因版本不兼容导致的基础故障;
- 数据库连接的建立与关闭:对比
DriverManager
(简单场景)与DataSource
(连接池 / 企业场景)两种连接方式,详解 URL 格式、特殊字符处理、规范关闭流程,确保连接资源合理使用。
由于全文涵盖 JDBC 全流程实战(从基础到高可用)下一篇我将带你聚焦 “实战进阶”,深入讲解 JDBC 连接属性的精细化配置(性能优化、安全加密、高可用)、语句对象(Statement/PreparedStatement/CallableStatement)的实战技巧、结果集处理、大对象操作、事务管理、元数据应用、读写分离与高可用配置等核心内容,帮助开发者从 “会用” 到 “用好” KingbaseES JDBC,真正解锁 Java 与国产数据库的高效交互能力。