杰瑞科技汇

Java连接PostgreSQL,配置与代码示例详解?

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

Java连接PostgreSQL,配置与代码示例详解?-图1
(图片来源网络,侵删)

目前最常用和推荐的 PostgreSQL JDBC 驱动是 pgjdbc


第一步:环境准备

在开始之前,请确保您已经安装并配置好了以下软件:

  1. Java Development Kit (JDK): 确保您的系统上安装了 JDK (建议 JDK 8 或更高版本) 并且配置了 JAVA_HOME 环境变量。
  2. PostgreSQL 数据库: 您需要有一个正在运行的 PostgreSQL 实例,并且已经创建了一个数据库和可以访问该数据库的用户。
  3. 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 项目中,根据您使用的构建工具,选择以下一种方式:

Java连接PostgreSQL,配置与代码示例详解?-图2
(图片来源网络,侵删)

使用 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 文件:

Java连接PostgreSQL,配置与代码示例详解?-图3
(图片来源网络,侵删)
  1. 访问 Maven 中央仓库: https://mvnrepository.com/artifact/org.postgresql/postgresql
  2. 找到最新的版本,下载 .jar 文件。
  3. 将下载的 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 + " 的用户。");
            }
        }
    }
}

代码解释

  1. DriverManager.getConnection(): 这是建立连接的核心方法,它需要三个参数:
    • DB_URL: 数据库的 URL,格式为 jdbc:postgresql://<主机名>:<端口>/<数据库名>
    • USER: 数据库用户名。
    • PASS: 用户密码。
  2. try-with-resources: try (Connection conn = ...) 这种写法会自动在 try 块结束时调用 conn.close(),即使发生异常也能确保资源被释放,是 Java 7+ 推荐的最佳实践。
  3. Statement: 用于执行简单的、不带参数的 SQL 查询。
  4. PreparedStatement: 用于执行带参数的 SQL 查询。强烈推荐使用它,因为它可以防止 SQL 注入攻击,并且对于需要多次执行的 SQL,性能更好。
  5. 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 中的 localhost5432 (默认端口) 是否正确,如果数据库不在本机,请使用正确的 IP 地址或主机名。
    • 检查防火墙: 确保防火墙没有阻止 5432 端口的连接。
    • 检查数据库是否存在: 确认 URL 中的数据库名称正确。

FATAL: password authentication failed for user "java_user"

  • 原因: 用户名或密码错误。
  • 解决方案:
    • 仔细检查 USERPASS 变量中的用户名和密码是否与您在 PostgreSQL 中创建的一致。
    • 确认该用户是否有权访问指定的数据库。

The connection attempt failed.

  • 原因: 这通常是网络或配置问题,错误信息会更具体,常见原因包括 SSL/TLS 配置不匹配。
  • 解决方案:
    • 检查 PostgreSQL 服务器配置文件 (postgresql.conf) 中的 listen_addresses 是否设置为 或 'localhost'
    • 检查 pg_hba.conf (Host-Based Authentication) 文件,确保客户端 IP 地址或主机名被允许以正确的认证方式(如 md5scram-sha-256)连接。
    • 如果数据库要求 SSL 连接,您可能需要配置 SSL,可以在 JDBC URL 中添加参数, jdbc:postgresql://localhost:5432/myjavaapp?ssl=true&sslmode=require

高级主题:连接池

对于生产环境的应用程序,频繁地创建和销毁数据库连接是非常消耗资源的。使用连接池是标准做法。

连接池会预先创建一组数据库连接,并将它们保存在一个池中,当应用程序需要连接时,从池中获取一个,用完后归还给池,而不是关闭,这极大地提高了性能。

流行的 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 数据库!

分享:
扫描分享到社交APP
上一篇
下一篇