Oracle 21c JDBC中JSON类型需显式启用支持:使用ojdbc11+、URL加oracle.jdbc.json=true、注册OracleType.JSON映射,再通过rs.getObject(col, JsonStructure.class)读取或ps.setObject(val, OracleType.JSON)写入。
Oracle 21c JSON类型在JDBC中默认映射为String,不是JSON对象
oracle 21c 支持原生 json 类型,但 jdbc 驱动(即使使用 ojdbc11)默认仍将其作为 varchar2 或 clob 返回——你拿到的只是 json 字符串,不是可导航的 java 对象。想用 json_object、json_array 等函数生成的值做结构化操作,必须显式启用 json 支持。
关键前提是:使用 Oracle 提供的官方 JSON 开发工具包(oracle.json),而非 Jackson 或 Gson。它和数据库内建 JSON 函数深度对齐,支持路径查询、修改、验证等,且能直接与 JDBC 的 OracleType.JSON 协同工作。
- 必须使用 ojdbc11(21.10+)或更高版本,低版本不识别
OracleType.JSON - 需在连接 URL 中添加
?oracle.jdbc.json=true启用 JSON 类型支持 - 驱动类名必须是
oracle.jdbc.OracleDriver(非oracle.jdbc.driver.OracleDriver)
如何从ResultSet中安全读取JSON列并转为JsonStructure
不能直接调用 rs.getString("col"),否则丢失类型信息,也无法利用 Oracle JSON 工具包的解析优化。正确方式是使用 rs.getObject("col", JsonStructure.class),前提是已注册类型映射。
示例代码片段:
// 注册 JSON 类型映射(只需一次,通常在 DataSource 初始化时)
connection.setTypeMap(Map.of(OracleType.JSON, JsonStructure.class));
// 查询时
ResultSet rs = stmt.executeQuery("SELECT data FROM my_table WHERE id = 1");
if (rs.next()) {
JsonStructure json = rs.getObject("data", JsonStructure.class);
// 此时 json 是 oracle.json.parser.JsonParserImpl$JsonObjectImpl 实例
// 可安全调用 get("name").asNumber()、getArray("items").get(0).asString() 等
}
- 若未注册 typeMap,
getObject(..., JsonStructure.class)会抛SQLFeatureNotSupportedException - 不要用
rs.getClob("data")再手动 parse,那样绕过了 Oracle 驱动的 JSON 校验和二进制优化 -
JsonStructure是只读接口;如需修改,用Json.createBuilderFactory().createObjectBuilder()构建新结构
如何把Java对象写入Oracle JSON列(INSERT/UPDATE)
Oracle 不接受任意 JSON 字符串:必须是语法合法、且通过 JSON_CHECK 约束校验的值。最稳妥的方式是先构造 JsonStructure,再通过 PreparedStatement.setObject() 绑定。
立即学习“Java免费学习笔记(深入)”;
示例:
JsonStructure payload = Json.createObjectBuilder()
.add("id", 101)
.add("tags", Json.createArrayBuilder().add("java").add("json"))
.add("active", true)
.build();
PreparedStatement ps = conn.prepareStatement("INSERT INTO my_table(id, data) VALUES (?, ?)");
ps.setInt(1, 101);
ps.setObject(2, payload, OracleType.JSON); // 显式指定 SQL 类型
ps.executeUpdate();
- 必须传
OracleType.JSON作为第三个参数,否则驱动按字符串处理,可能触发隐式转换失败 - 如果 payload 是
String,需先用Json.createReader(new StringReader(str)).read()解析,否则插入后无法被JSON_EXISTS等函数识别 - Oracle 21c 支持
JSON_VALUE提取标量,但要求源列是真正 JSON 类型,不是 VARCHAR2 存的 JSON 文本
常见报错及绕过陷阱
遇到 ORA-40442: JSON syntax error 或 ORA-40590: invalid JSON path expression 时,问题往往不在 SQL,而在 Java 层绑定方式。
-
setString(2, "{\"a\":1}")→ 触发 ORA-40442:驱动未识别 JSON 类型,数据库收到的是带引号的字符串字面量 - 使用旧版 ojdbc8 → 报
SQLFeatureNotSupportedException: getObject with type:升级到 ojdbc11 是硬性前提 - 连接 URL 缺少
oracle.jdbc.json=true→OracleType.JSON被忽略,回退为字符串处理 - JSON 值含 Unicode 控制字符(如 \u0000)→ Oracle JSON 类型拒绝存储,需提前清理或改用 BLOB 存储原始文本
真正麻烦的点在于:错误发生在执行时,且堆栈不提示 Java 层绑定问题,容易误判为 SQL 或数据问题。最简单的验证方式是查 SELECT DUMP(data) FROM my_table —— 如果返回 TYP=113(JSON 类型码),说明成功;若是 TYP=1(VARCHAR2),说明绑定失败。


















