最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如何将Oracle JSON字段映射为Java对象
时间:2026-08-08 11:09:55 编辑:袖梨 来源:一聚教程网
唯一安全的读取方式是 rs.getObject("col", String.class),因 Oracle 19c 原生 JSON 列需显式协议支持,该方法底层绑定 SQLType.JSON(ojdbc8u3+),返回 null 而非空字符串,其他方式均可能抛异常或乱码。
rs.getObject("col", String.class) 是唯一安全的读取方式
Oracle 19c 的原生 JSON 列在 JDBC 中不会自动转成字符串,rs.getString("col") 大概率抛出 SQLException: cannot convert to string 或返回乱码二进制(如 0x7B2261223A317D)。根本原因不是字符集问题,而是驱动把 JSON 当作独立 SQL 类型处理,必须显式声明协议。
正确做法只有一种:rs.getObject("col", String.class)。它底层依赖 SQLType.JSON 协议,但你不需要手动传入 SQLType.JSON 参数——ojdbc8u3+(即 19.19+)已将 String.class 绑定到该协议。传其他类型(如 JsonObject.class)会直接报 SQLFeatureNotSupportedException。
- 驱动版本必须 ≥
ojdbc8u3(19.19),ojdbc7等旧版连JSON类型都不识别,会报ORA-00902: invalid datatype - 字段为 NULL 时,
rs.getObject("col", String.class)返回null,不是空字符串 - 别试
rs.getNString()、rs.getClob()或rs.getObject("col")(后者返回oracle.sql.json.OracleJsonStructure,不能直接toString())
用 Jackson 反序列化字符串为 Java 对象
拿到 String 后,交给 Jackson(推荐 ObjectMapper)做反序列化。这不是 JDBC 层的事,JDBC 只负责吐出合规 JSON 字符串。
关键点在于类结构要与 JSON 严格匹配:字段名、嵌套层级、集合类型都得一致;所有字段需有 public getter/setter(Jackson 默认靠反射调用);无参构造函数必须存在。
- 示例:若 JSON 是
{"name":"Alice","age":25},对应类必须有getName()、setName(String)、getAge()、setAge(int)和无参构造函数 - 嵌套数组(如
"systems": [{"id":1,"name":"sys1"}])需定义List字段,并确保SystemInfo类也满足上述要求 - 避免用
Map临时替代——它绕过编译检查,嵌套访问易错,且无法校验字段必填性
MyBatis/Spring JDBC 不会自动解析 JSON 列
MyBatis 的 BeanPropertyRowMapper 和 Spring JDBC 的默认映射机制,对 Oracle 原生 JSON 列完全无感知。它们只认标准 JDBC 类型(VARCHAR、NUMBER 等),遇到 JSON 列会 fallback 到通用类型处理,大概率失败或返回乱码。
必须手动干预:
- MyBatis:写自定义
TypeHandler,在getResult(ResultSet rs, String column)里调用rs.getObject(column, String.class),再用 Jackson 解析 - Spring JDBC:用
ResultSetExtractor或RowMapper,同样先取String,再反序列化 - 别指望
@Column或@Convert注解自动生效——JPA 规范不定义 JSON 类型映射,Hibernate 需额外配置方言或自定义转换器
写入 JSON 字段:用 writeValueAsString + setClob
往 JSON 列写数据时,JDBC 不提供原生支持。你得自己保证输入是合法 JSON 字符串,再按常规方式写入。
- 小 JSON(确定 ≤ 4000 字节):用
ps.setString(idx, objectMapper.writeValueAsString(obj)) - 大 JSON:必须用
ps.setClob(idx, new SerialClob(objectMapper.writeValueAsString(obj).toCharArray())),否则可能触发 ORA-01461(bind variable type mismatch) - 千万别直接
ps.setObject(idx, obj)——驱动不认识你的 POJO,会尝试转成 STRUCT,失败 - 服务端字符集必须是
AL32UTF8,JDBC URL 加?useUnicode=true&characterEncoding=UTF-8防止中文乱码
rs.getObject("col", String.class):它依赖驱动版本、必须用 String.class、不能省略参数、NULL 返回值要单独判空——漏掉任一环,都会在运行时崩。
相关文章
- 遗忘之海双区域海妖歌声彩蛋位置一览 全隐藏彩蛋点位在哪 08-08
- 遗忘之海双海域拼图答题彩蛋位置一览 全隐藏彩蛋点位在哪 08-08
- 遗忘之海白沙海鲸鱼宝箱位置一览 全隐藏彩蛋点位在哪 08-08
- iphone14pro max运行内存介绍 08-08
- 逆战未来炼狱难度联盟大厦通关攻略 炼狱难度联盟大厦如何打 08-08
- 逆战未来骇影入侵玩法攻略 骇影入侵如何玩 08-08