Java PreparedStatement 插入 JSON 对象到 PostgreSQL

1、简介

在现代软件开发中,由于 JSON 数据的轻量和通用性,处理 JSON 数据已经变得无处不在。PostgreSQL 凭借其对 JSON 的强大支持,为存储和查询 JSON 数据提供了出色的平台。

在 Java 中,我们通常使用 JDBC 与数据库进行交互,本文将带你了解如何使用 Java 的 PreparedStatement 将 JSON 对象插入 PostgreSQL 数据库。

2、依赖

首先,需要设置环境。除了安装和运行 PostgreSQL,还需要在项目的依赖中添加 PostgreSQL JDBC 驱动和 org.json 库。

2.1、安装和运行 PostgreSQL

如果你还没有安装 PostgreSQL,可以从 PostgreSQL 官方网站 下载并安装。PostgreSQL 支持 JSON 已经有相当长的时间了,你可以选择从 PostgreSQL 9 开始的任何版本。本文使用最新的稳定版本,即 PostgreSQL 16

在继续阅读之前,你需要确保 PostgreSQL 正常运行,并可通过必要的凭据访问。

2.2、添加 PostgreSQL JDBC 驱动

将 PostgreSQL JDBC 驱动添加到项目的依赖中。

对于 Maven 项目,可以在 pom.xml 中添加如下 依赖

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.7.3</version>
</dependency>

2.3、添加 JSON 依赖

要在 Java 代码中处理 JSON 数据,还需要添加 JSON 库依赖。目前有几种流行的 Java JSON 库,如 JacksonGsonFastJsonorg.json。在本文中,我们使用 org.json 库,它提供了一个简单、轻量级的 JSON 处理解决方案。

要在项目中添加 org.json 库,可以在 Maven 项目的 pom.xml 文件中添加以下 依赖

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20240303</version>
</dependency>

必要的依赖添加完毕后,接下来创建数据表,并编写插入 JSON 数据的 Java 代码。

3、JSONB 和 JSON

PostgreSQL 为存储 JSON 数据提供了两种主要类型:JSONBJSON。虽然这两种类型都能实现存储和处理 JSON 数据,但它们还是有一些区别。

JSONB 类型具有高效的二进制存储和索引功能,因此查询执行速度更快。它能在插入过程中对 JSON 数据进行验证和转换,并保留 JSON 对象中 KEY 的顺序。PostgreSQL 可以自动将其他数据类型的值转换为 JSON。

而,JSON 类型将 JSON 数据存储为纯文本,没有二进制表示或专门的索引。它在插入过程中执行验证,但缺乏 JSONB 的优化和 KEY 的有序性。使用 JSONB 类型时,需要进行显式转换,才能将值转换为 JSON。

在本文中,我们使用 JSONB 类型在 PostgreSQL 中存储和查询 JSON 数据。

4、创建带 JSON 列的 PostgreSQL 表

首先,需要创建一个包含 JSON 列的 PostgreSQL 表。

连接到上文设置的 PostgreSQL 实例,然后运行以下 SQL 命令:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    -- JSONB 类型的 JSON 列
    info JSONB 
);

该表有三列:idnameinfoinfo 列的类型是 JSONB,它以二进制格式存储 JSON 数据,提供高效的存储和查询功能。

5、Java 插入 JSON 数据

现在,进入 Java 编码环节。我们要编写一个 Java 程序,使用 PreparedStatementusers 表中插入 JSON 数据。

5.1、建立数据库连接

首先,需要建立与 PostgreSQL 数据库的 JDBC 连接。

下面是获取数据库连接的方法:

public class InsertJsonData {
    private static final String URL = "jdbc:postgresql://localhost:5432/database_name";
    private static final String USER = "username";
    private static final String PASSWORD = "password";

    // 获取数据库 JDBC 连接
    public Connection getConnection() throws SQLException {
        return DriverManager.getConnection(URL, USER, PASSWORD);
    }
}

注意database_nameusernamepassword 需要替换为你实际的 PostgreSQL 数据库名称、用户名和密码。

5.2、插入 JSON 数据

接下来,编写一个向 users 表中插入 JSON 对象的方法:

public class InsertJsonData {
    public static void insertUser(String name, JSONObject info) {
        String sql = "INSERT INTO users (name, info) VALUES (?, ?::jsonb)";

        Connection conn = DatabaseConnection.getConnection();
        PreparedStatement pstmt = conn.prepareStatement(sql);

        pstmt.setString(1, name);
        // JSON 对象序列化为字符串格式
        pstmt.setString(2, info.toString());
        pstmt.executeUpdate();

        System.out.println("Data inserted successfully.");
    }

    public static void main(String[] args) {
        JSONObject jsonInfo = new JSONObject();
        jsonInfo.put("email", "john.doe@example.com");
        jsonInfo.put("age", 30);
        jsonInfo.put("active", true);

        insertUser("John Doe", jsonInfo);
    }
}

如上,要点如下:

  • 数据库连接:getConnection() 方法可建立与 PostgreSQL 数据库的连接。
  • SQL 查询:INSERT INTO users (name, info) VALUES (?, ?::jsonb) 查询会在 users 表中插入一条记录。?::jsonb 语法是 PostgreSQL 特有的语法,用于类型转换。双冒号操作符 :: 是 PostgreSQL 中 CAST 关键字的同义词,表示类型转换操作。通过使用 ?::jsonb,我们指定 PostgreSQL 将第二个参数(一个 JSON 字符串)转换为 jsonb 数据类型,然后再将其插入 info 列。这样就可以在 PostgreSQL 中正确处理和存储 JSON 数据。
  • PreparedStatement:PreparedStatement 设置参数并执行 SQL 查询。pstmt.setString(1, name) 设置 name 参数,pstmt.setString(2, info.toString()) 设置 info 参数,即 JSON 数据。
  • JSON 处理:org.json 库中的 JSONObject 类可用于创建和处理 JSON 数据。

6、总结

使用 Java 的 PreparedStatement 将 JSON 对象插入 PostgreSQL 既简单又高效。这种方法利用了 PostgreSQL 强大的 JSON 功能和 Java 强大的 JDBC API。按照本文概述的步骤,你可以在 PostgreSQL 数据库中无缝存储 JSON 数据,并利用其丰富的查询功能。

如果是你使用的是 JPA(Java Persistence API),其实会更加的方便。你可以参阅 “使用 Spring Data JPA 在 PostgreSQL 中存储和检索 JSON 数据” 这篇文章了解详情。


Ref:https://www.baeldung.com/java-postgresql-insert-json-object-preparedstatement