mysql 5.7+ 应使用原生 json 类型建表并配合 jacksontypehandler 映射为 string,读取后用有序解析(如 linkedhashmap)保留结构与顺序,写入前须序列化校验,查询 json 内字段应建虚拟列+索引。

MySQL 5.7+ 原生支持 JSON 类型字段,Java 中正确操作它,关键在于**类型映射准确、序列化/反序列化可控、查询逻辑清晰**。直接用 String 存取虽能跑通,但会丢失结构语义、无法利用 MySQL 的 JSON 函数、容易引发顺序错乱或类型转换异常。
建表与字段定义要明确使用 JSON 类型
不要用 TEXT 或 VARCHAR 代替 JSON 字段。MySQL 对 JSON 类型有格式校验、函数支持和优化能力:
- 建表示例:
CREATE TABLE user_profile (id BIGINT PRIMARY KEY, info JSON); - 插入时可直接传合法 JSON 字符串:
INSERT INTO user_profile VALUES (1, '{"name":"张三","tags":["java","spring"]}'); - 也可用函数构造:
INSERT INTO user_profile VALUES (2, JSON_OBJECT('name', '李四', 'age', 28));
Java 实体类中推荐用 String 接收,但需配合 TypeHandler
MyBatis 默认不识别 JSON 类型,直接映射为 String 最简单且安全。但必须确保写入前是合法 JSON 字符串,读取后能按需解析:
- 实体类字段声明为
private String info;(不是Map或Object) - MyBatis XML 映射中指定 typeHandler:
<result column="info" property="info" typehandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"></result> - 或使用 MyBatis-Plus 的
@TableField(typeHandler = JacksonTypeHandler.class) - 避免用
Object或泛型Map直接接收——Jackson 默认解析为LinkedHashMap,但字段顺序不保证,且嵌套结构易出错
读取后解析要保留结构与顺序
从数据库查出的 info 是字符串,需用 Jackson/Gson 解析。若原始 JSON 中字段顺序重要(如前端渲染依赖顺序),必须显式启用有序解析:
- 用 Jackson:
ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.USE_ORDERED_MAP, true); Map<string object> data = mapper.readValue(jsonStr, new TypeReference<linkedhashmap object>>() {});</linkedhashmap></string> - 用 Fastjson(旧项目):
JSON.parseObject(jsonStr, LinkedHashMap.class, Feature.OrderedField); - 不要依赖
JSONObject.toJavaObject()或默认Map—— 它可能返回HashMap,顺序丢失
写入前必须校验并生成合法 JSON 字符串
Java 端构造数据后,应统一序列化为标准 JSON 字符串再入库,而非拼接字符串:
- 推荐方式:用 Jackson 序列化 POJO 或 Map:
String jsonStr = mapper.writeValueAsString(userExtraInfo); - 确保 POJO 字段命名与 JSON key 一致(可用
@JsonProperty控制) - 禁止手动拼接
"{...}"—— 容易引号、转义、空值出错 - 若存的是 List,也先序列化:
mapper.writeValueAsString(Arrays.asList(obj1, obj2))
不复杂但容易忽略:MySQL 的 JSON 字段本身不索引内容,如需按 JSON 内某字段查询(如 $.name),应建虚拟列 + 普通索引,而不是在 Java 层全量拉取再过滤。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











