Java 连接 PostgreSQL 数据库主要依赖于一个 JDBC (Java Database Connectivity) 驱动程序,这个驱动程序充当了 Java 应用程序和 PostgreSQL 数据库之间的桥梁,使得 Java 代码能够发送 SQL 查询并处理结果。

目前最常用和推荐的 PostgreSQL JDBC 驱动是 pgjdbc。
第一步:环境准备
在开始之前,请确保您已经安装并配置好了以下软件:
- Java Development Kit (JDK): 确保您的系统上安装了 JDK (建议 JDK 8 或更高版本) 并且配置了
JAVA_HOME环境变量。 - PostgreSQL 数据库: 您需要有一个正在运行的 PostgreSQL 实例,并且已经创建了一个数据库和可以访问该数据库的用户。
- IDE (集成开发环境): 如 IntelliJ IDEA, Eclipse, VS Code 等,用于编写和运行 Java 代码。
数据库准备示例:
使用 psql 命令行工具连接到您的 PostgreSQL 服务器,并执行以下 SQL 命令:
-- 创建一个新数据库,myjavaapp CREATE DATABASE myjavaapp; -- 创建一个新用户,java_user,并设置密码 CREATE USER java_user WITH PASSWORD 'your_password'; -- 授予该用户对新数据库的所有权限 GRANT ALL PRIVILEGES ON DATABASE myjavaapp TO java_user;
第二步:添加 JDBC 驱动依赖
您需要将 PostgreSQL JDBC 驱动程序添加到您的 Java 项目中,根据您使用的构建工具,选择以下一种方式:

使用 Maven (推荐)
如果您使用 Maven 管理项目,请在您的 pom.xml 文件中添加以下依赖:
<dependencies>
<!-- PostgreSQL JDBC Driver -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.3</version> <!-- 建议使用最新版本 -->
</dependency>
</dependencies>
Maven 会自动下载并管理这个依赖。
使用 Gradle
如果您使用 Gradle,请在您的 build.gradle 文件中添加以下依赖:
dependencies {
// PostgreSQL JDBC Driver
implementation 'org.postgresql:postgresql:42.7.3' // 建议使用最新版本
}
手动下载 JAR 文件
如果您不使用构建工具,可以手动下载 JAR 文件:

- 访问 Maven 中央仓库: https://mvnrepository.com/artifact/org.postgresql/postgresql
- 找到最新的版本,下载
.jar文件。 - 将下载的 JAR 文件添加到您的项目的类路径中,在 IDE 中,通常右键点击项目 -> Build Path / Project Structure -> Libraries -> Add External JARs。
第三步:编写 Java 连接代码
我们可以编写 Java 代码来连接数据库了,一个健壮的连接应该包括 try-with-resources 语句,以确保连接、语句和结果集在使用后能被正确关闭。
完整示例代码
下面是一个完整的示例,展示了如何连接、查询、插入和更新数据。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class PostgresJdbcExample {
// 数据库连接信息
// 建议将敏感信息(如密码)存储在配置文件中,而不是硬编码在代码里
private static final String DB_URL = "jdbc:postgresql://localhost:5432/myjavaapp";
private static final String USER = "java_user";
private static final String PASS = "your_password";
public static void main(String[] args) {
// --- 1. 使用 try-with-resources 确保连接关闭 ---
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS)) {
if (conn != null) {
System.out.println("成功连接到 PostgreSQL 数据库!");
} else {
System.out.println("连接失败!");
return;
}
// --- 2. 创建表并插入数据 (仅第一次运行时需要) ---
createAndInsertData(conn);
// --- 3. 查询数据 ---
queryData(conn);
// --- 4. 使用 PreparedStatement 更新数据 (防止SQL注入) ---
updateData(conn, 1, "Alice Updated");
} catch (SQLException e) {
System.err.println("数据库操作出错!");
e.printStackTrace();
}
}
/**
* 创建表并插入一些示例数据
*/
private static void createAndInsertData(Connection conn) throws SQLException {
// 使用 try-with-resources 自动关闭 Statement
try (Statement stmt = conn.createStatement()) {
// 创建表
String createTableSQL = "CREATE TABLE IF NOT EXISTS users ("
+ "id SERIAL PRIMARY KEY, "
+ "name VARCHAR(50) NOT NULL, "
+ "email VARCHAR(50) UNIQUE NOT NULL"
+ ");";
stmt.executeUpdate(createTableSQL);
System.out.println("表 'users' 已创建或已存在。");
// 插入数据 (如果不存在)
String insertSQL = "INSERT INTO users (name, email) VALUES (?, ?) ON CONFLICT (email) DO NOTHING;";
try (PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {
pstmt.setString(1, "Alice");
pstmt.setString(2, "alice@example.com");
pstmt.executeUpdate();
System.out.println("插入了 Alice 的数据。");
pstmt.setString(1, "Bob");
pstmt.setString(2, "bob@example.com");
pstmt.executeUpdate();
System.out.println("插入了 Bob 的数据。");
}
}
}
/**
* 查询并打印表中的所有数据
*/
private static void queryData(Connection conn) throws SQLException {
String selectSQL = "SELECT id, name, email FROM users;";
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(selectSQL)) {
System.out.println("\n--- 用户列表 ---");
while (rs.next()) {
// 通过列名获取数据,更具可读性且不易出错
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
System.out.println("ID: " + id + ", Name: " + name + ", Email: " + email);
}
}
}
/**
* 使用 PreparedStatement 更新用户信息
*/
private static void updateData(Connection conn, int id, String newName) throws SQLException {
String updateSQL = "UPDATE users SET name = ? WHERE id = ?;";
try (PreparedStatement pstmt = conn.prepareStatement(updateSQL)) {
pstmt.setString(1, newName);
pstmt.setInt(2, id);
int affectedRows = pstmt.executeUpdate();
if (affectedRows > 0) {
System.out.println("\n成功更新 ID 为 " + id + " 的用户名为 " + newName);
} else {
System.out.println("\n未找到 ID 为 " + id + " 的用户。");
}
}
}
}
代码解释
- DriverManager.getConnection(): 这是建立连接的核心方法,它需要三个参数:
DB_URL: 数据库的 URL,格式为jdbc:postgresql://<主机名>:<端口>/<数据库名>。USER: 数据库用户名。PASS: 用户密码。
- try-with-resources:
try (Connection conn = ...)这种写法会自动在try块结束时调用conn.close(),即使发生异常也能确保资源被释放,是 Java 7+ 推荐的最佳实践。 - Statement: 用于执行简单的、不带参数的 SQL 查询。
- PreparedStatement: 用于执行带参数的 SQL 查询。强烈推荐使用它,因为它可以防止 SQL 注入攻击,并且对于需要多次执行的 SQL,性能更好。
- ResultSet: 表示 SQL 查询返回的结果集,通过
rs.next()方法可以遍历每一行数据,rs.getXXX("列名")方法可以获取列的值。
第四步:处理常见问题
No suitable driver found for jdbc:postgresql://...
- 原因: JDBC 驱动没有被加载到类路径中。
- 解决方案:
- 确保您已经正确地添加了
postgresql.jar依赖。 - 如果手动添加 JAR,请检查 IDE 的项目配置中,该 JAR 是否在 Libraries 或 Build Path 中。
- 在某些旧版 Java 或特殊环境下,可能需要显式加载驱动类(虽然现代 JDBC 驱动通常不需要):
Class.forName("org.postgresql.Driver");。
- 确保您已经正确地添加了
Connection refused: connect
- 原因: Java 应用程序无法连接到 PostgreSQL 服务器。
- 解决方案:
- 检查 PostgreSQL 服务是否正在运行: 使用
pg_isready -h localhost -p 5432命令检查。 - 检查主机和端口: 确认
DB_URL中的localhost和5432(默认端口) 是否正确,如果数据库不在本机,请使用正确的 IP 地址或主机名。 - 检查防火墙: 确保防火墙没有阻止 5432 端口的连接。
- 检查数据库是否存在: 确认 URL 中的数据库名称正确。
- 检查 PostgreSQL 服务是否正在运行: 使用
FATAL: password authentication failed for user "java_user"
- 原因: 用户名或密码错误。
- 解决方案:
- 仔细检查
USER和PASS变量中的用户名和密码是否与您在 PostgreSQL 中创建的一致。 - 确认该用户是否有权访问指定的数据库。
- 仔细检查
The connection attempt failed.
- 原因: 这通常是网络或配置问题,错误信息会更具体,常见原因包括 SSL/TLS 配置不匹配。
- 解决方案:
- 检查 PostgreSQL 服务器配置文件 (
postgresql.conf) 中的listen_addresses是否设置为 或'localhost'。 - 检查
pg_hba.conf(Host-Based Authentication) 文件,确保客户端 IP 地址或主机名被允许以正确的认证方式(如md5或scram-sha-256)连接。 - 如果数据库要求 SSL 连接,您可能需要配置 SSL,可以在 JDBC URL 中添加参数,
jdbc:postgresql://localhost:5432/myjavaapp?ssl=true&sslmode=require
- 检查 PostgreSQL 服务器配置文件 (
高级主题:连接池
对于生产环境的应用程序,频繁地创建和销毁数据库连接是非常消耗资源的。使用连接池是标准做法。
连接池会预先创建一组数据库连接,并将它们保存在一个池中,当应用程序需要连接时,从池中获取一个,用完后归还给池,而不是关闭,这极大地提高了性能。
流行的 Java 连接池库:
- HikariCP: 目前性能最好、最流行的连接池,是 Spring Boot 2.x 的默认选择。
- Apache DBCP (Database Connection Pool): 一个老牌的、稳定的连接池实现。
- C3P0: 另一个广泛使用的连接池。
使用 HikariCP 的示例:
在 pom.xml 中添加 HikariCP 依赖:
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.1.0</version> <!-- 使用最新版本 -->
</dependency>
修改代码以使用 HikariCP 管理连接:
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class PostgresWithHikariExample {
// HikariCP 数据源 (单例模式)
private static HikariDataSource dataSource;
static {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:postgresql://localhost:5432/myjavaapp");
config.setUsername("java_user");
config.setPassword("your_password");
config.setDriverClassName("org.postgresql.Driver");
// 连接池配置 (可以根据需要调整)
config.setMaximumPoolSize(10); // 最大连接数
config.setMinimumIdle(5); // 最小空闲连接数
config.setConnectionTimeout(30000); // 连接超时时间 (毫秒)
config.setIdleTimeout(600000); // 空闲超时时间
config.setMaxLifetime(1800000); // 连接最大存活时间
dataSource = new HikariDataSource(config);
}
public static void main(String[] args) {
// 从连接池获取连接
try (Connection conn = dataSource.getConnection()) {
System.out.println("从 HikariCP 连接池成功获取连接!");
// 执行查询...
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users;")) {
while (rs.next()) {
System.out.println("ID: " + rs.getInt("id") + ", Name: " + rs.getString("name"));
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 当应用程序关闭时,关闭数据源
if (dataSource != null && !dataSource.isClosed()) {
dataSource.close();
}
}
}
}
希望这份详细的指南能帮助您成功地在 Java 中连接和使用 PostgreSQL 数据库!
