一聚教程网:一个值得你收藏的教程网站

热门教程

如何在Oracle 21c中使用原生JSON数据类型?

时间:2026-08-30 09:18:47 编辑:袖梨 来源:一聚教程网

Oracle 21c 中 JSON 是原生类型,但建表需避让保留字(如 add→address)、必须加 CHECK(soc IS JSON) 约束,JDBC 需 ojdbc11 驱动+oracle.jdbc.json=true 参数及 JsonStructure 映射。

JSON 类型在 Oracle 21c 中是真实可用的原生类型,不是伪类型或 CHECK 约束模拟。但直接写 soc JSON 就建表会失败——因为列名冲突或驱动/语法版本不匹配是最常见拦路虎。


CREATE TABLE 时 JSON 列名不能是 Oracle 保留字

ADD 是 Oracle 的保留关键字(用于 ALTER TABLE ... ADD),所以这个建表语句:

CREATE TABLE a (name VARCHAR2(50), age NUMBER, add VARCHAR2(100), soc JSON);

必然报 ORA-00904: invalid identifier,和 JSON 类型本身无关。

  1. add 改成 addressaddr 或其他非保留字即可
  2. 强行用双引号包住:"add" 虽然能过语法检查,但后续所有 SQL 都得带引号、大小写敏感、ORM 映射大概率崩,不建议
  3. 其他常见踩坑列名:ORDERLEVELTYPEVALUE —— 建表前先查 V$RESERVED_WORDS

JSON 列必须配合 IS JSON 检查约束才生效

Oracle 21c 的 JSON 类型不是“开箱即用”的强类型:它底层依赖 OSON 二进制格式,但仅靠列声明 soc JSON 不自动启用校验或索引优化。

  1. 必须显式加 CHECK (soc IS JSON),否则插入非法 JSON 不报错,后续 JSON_VALUE 可能静默返回 NULL
  2. 这个约束不是可选的“锦上添花”,而是触发数据库启用 JSON 语义解析的前提
  3. 不要只写 CHECK (soc IS JSON STRICT):21c 默认就是 STRICT 模式,STRICT 关键字多余,还可能在某些补丁版本报错

JDBC 读取 JSON 列必须启用 oracle.jdbc.json=true

即使表结构完全正确,Java 程序默认拿到的仍是 StringCLOB,不是可导航的 JSON 对象。

  1. 连接 URL 必须带参数:?oracle.jdbc.json=true(例如:jdbc:oracle:thin:@//host:1521/orclpdb?oracle.jdbc.json=true
  2. 驱动必须是 ojdbc11(21.10+),ojdbc8 不识别该参数,会静默忽略
  3. ResultSet.getObject("soc", JsonStructure.class) 才能拿到 oracle.json.parser.JsonParserImpl$JsonObjectImpl 实例;用 getString()getClob() 会丢失 OSON 二进制优势,且无法调用 .get("x").asNumber() 等方法
  4. 如果用 Spring JdbcTemplate,需在 DataSource 初始化时注册类型映射:connection.setTypeMap(Map.of(OracleType.JSON, JsonStructure.class))

写入大 JSON 或含二进制内容时,别依赖 setString()

JSON 列支持 OSON 格式,但 JDBC 层不自动转换:

  1. 纯文本 JSON 字符串({"name":"a"})可用 PreparedStatement.setString(),但长度超过 4000 字节时,ojdbc11 可能截断或报 ORA-40495
  2. 含二进制字段(如 Base64 图片)必须用 setBytes() + UTL_RAW.CAST_TO_RAW() 包装,或走 setClob() 配合 StringReader
  3. 最稳妥方式:统一用 OraclePreparedStatement.setObject(colIndex, jsonValue, OracleType.JSON),其中 jsonValueJsonStructure 实例(由 Json.createStructure() 构造)

最易被忽略的一点:21c 的 JSON 类型和 19c 的 JSON 列行为不兼容——前者强制 OSON 存储、后者仍是文本+CHECK,混用会导致 JDBC 读取逻辑彻底失效。

热门栏目