操作 JSON 如丝般顺滑,MongoDB 已哭晕在厕所

数据库 MariaDB
随着数字化技术应用到各行各业,数据库需要处理的数据结构也变得越来越丰富。这时候,很多应用就会考虑引入 JSON 这种更灵活的半结构化类型了。

介绍

从 v9.2 开始,PostgreSQL 为 JSON 对象提供了原生数据类型的支持。后续版本引入了 JSONB(二进制格式化的 JSON 对象)和许多 JSON 数据操作函数,使其成为 NoSQL 操作方面非常强大的工具。

字符串操作和解析在数据库中是高开销的操作,因此,尽管您之前可能在 PostgreSQL 中以字符串形式存储 JSON 对象,但原生数据类型的引入消除了开销,并使 JSON 操作的吞吐量大大加快。

JSON 和 JSONB

在 PostgreSQL v9.4 中引入了原生数据类型 JSONB,它以二进制格式存储 JSON 对象。JSON 和 JSONB 之间的主要区别列出在下表中:

JSON

JSONB

以文本格式存储数据

以分解的二进制格式存储数据

输入速度快,因为不需要转换

输入速度稍慢,因为存在与二进制转换相关的开销

处理函数必须在每次执行时重新解析数据

无需重新解析,使数据处理速度明显加快

输入中的所有空格和换行符都按原样保留

去除多余的空白和换行符

不支持索引

支持索引

保留重复的键,处理函数只考虑最后一个值

重复的键在输入时被清除,只存储最后一个值

保留键的顺序

不保留键的顺序

JSON 数据定义

JSON 列的创建方式与任何其他数据类型一样。我们在下面创建一个表 'sales'(我们将在后续示例中使用),其中包含 2 列 'id' 和 'sale',后者是一个 JSON 列:

CREATE TABLE sales (id INT, sale JSON);

JSON 数据插入

JSON 数据类型会检查有效的 JSON 格式,因此 INSERT 语句应注意这一点。下面这个简单的 Java 程序,将 4 条记录插入到我们刚刚创建的表中。

String[] json = {
  "{\"customer_name\": \"John\", \"items\": { \"description\": \"milk\", \"quantity\": 4 } }",
  "{\"customer_name\": \"Susan\", \"items\": { \"description\": \"bread\", \"quantity\": 2 } }",
  "{\"customer_name\": \"Mark\", \"items\": { \"description\": \"bananas\", \"quantity\": 12 } }",
  "{\"customer_name\": \"Jane\", \"items\": { \"description\": \"cereal\", \"quantity\": 1 } }"};

try {
  String sql = "INSERT INTO sales VALUES (?, ?::JSON)";
  PreparedStatement ps = conn.prepareStatement(sql);

  for (int i=0; i<4; i++) {
    ps.setInt(1, i+1);
    ps.setObject(2, json[i]);
    ps.executeUpdate();
  }
  conn.commit();
} catch (Exception e) {
   System.out.println(e.getMessage());
   e.printStackTrace();
}

请注意字符串是如何在预备语句中转换为 JSON 的。

这是上面的数据插入后,在 psql 中的显示结果:

select * from sales;
 id | sale
----+-----------------------------------------------------------------------------------
 1  | {"customer_name": "John", "items": { "description": "milk", "quantity": 4 } }
 2  | {"customer_name": "Susan", "items": { "description": "bread", "quantity": 2 } }
 3  | {"customer_name": "Mark", "items": { "description": "bananas", "quantity": 12 } }
 4  | {"customer_name": "Jane", "items": { "description": "cereal", "quantity": 1 } }
(4 rows)

JSON 数据检索

在检索 JSON 数据时,您可以使用 PostgreSQL 原生运算符访问单个元素,也可以使用 Java 库提供的 JSONObject 处理 Java 中的对象。下面给出了两种情况的示例。

使用 PostgreSQL 运算符

PostgreSQL 提供了 '->' 运算符来检索 JSON 对象中各种键的值。下面的示例程序,检索 sale 的 ‘customer_name’ 列表,然后检索 ‘items’ 的 ‘description’ 列表。sale 是一个嵌入的 JSON。

try {
  /* Retrieving customer_name */
  String sql = "select sale->'customer_name' from sales";
  PreparedStatement ps = conn.prepareStatement(sql);
  ResultSet rs = ps.executeQuery();

  while(rs.next()) {
    System.out.println(rs.getString(1));
  }

  System.out.println("******************************************");

  /* Retrieving description, which is an embedded JSON */
  sql = "select sale->'items'->'description' from sales";
  ps = conn.prepareStatement(sql);
  rs = ps.executeQuery();

  while(rs.next()) {
    System.out.println(rs.getString(1));
  }
} catch (Exception e) {
  System.out.println(e.getMessage());
  e.printStackTrace();
}

上面程序的输出是:

"John"
"Susan"
"Mark"
"Jane"
******************************************
"milk"
"bread"
"bananas"
"cereal"

使用 JSONObject

为了在 Java 程序中使用 JSONObject,您需要在 CLASSPATH 中拥有其软件库的 jar 文件。jar 文件可以从许多位置免费获得,包括这个位置。基本的 JSON 操作将在下面介绍,但您可以在此处获取更多 API 详细信息。

下面的 Java 代码,可获得与上面演示的相同的结果:

try {
  /* Retrieving customer_name */
  String sql = "select sale from sales";
  Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
  ResultSet rs = stmt.executeQuery(sql);

  JSONObject json;
  JSONObject json2;

  while(rs.next()) {
    json = new JSONObject(rs.getString(1));
    System.out.println(json.get("customer_name"));
  }

  System.out.println("******************************************");

  /* Retrieving description, which is an embedded JSON */
  rs.first();

  do {
    json = new JSONObject(rs.getString(1));
    json2 = (JSONObject)json.get("items");
    System.out.println(json2.get("description"));
  } while(rs.next());
} catch (Exception e) {
  System.out.println(e.getMessage());
  e.printStackTrace();
}

该程序的输出为:

John
Susan
Mark
Jane
******************************************
milk
bread
bananas
cereal
责任编辑:武晓燕 来源: 红石PG
相关推荐

2024-12-06 08:20:22

BigDecimal浮点数初始化

2014-10-17 10:31:25

2015-05-14 14:24:27

互联网IT从业者

2017-08-15 10:20:08

Surface微软消费者

2020-12-30 05:29:48

API分库分表

2017-06-05 10:01:24

互联网

2019-04-04 17:15:13

2016-12-02 13:01:54

Android 7.1安卓

2017-10-31 13:20:00

H5翻页库框架

2018-03-29 09:05:07

Chrome 浏览器 Win10

2022-05-31 09:01:13

GitHub工具安全

2018-01-09 20:53:13

2013-10-08 16:54:32

微软云操作系统

2014-12-15 15:33:25

Google测试马桶

2022-10-10 09:41:54

LinuxWindowsWSL2

2023-03-28 08:40:22

命令行JSON用法

2015-10-28 17:35:51

资本

2015-07-17 15:23:52

中国网

2011-07-08 09:42:03

点赞
收藏

51CTO技术栈公众号