如何用Spring Data JPA将嵌套JSON存储到MySQL数据库?
如何将复杂嵌套JSON存储到MySQL及嵌套元素类的处理方案
针对你遇到的复杂嵌套JSON存储问题,提供两种主流解决方案,同时明确嵌套元素类的处理方式:
方案一:关系型数据库规范存储(需创建嵌套实体类)
这种方式遵循数据库设计范式,将嵌套数据拆分为多个关联表,适合需要频繁查询、修改嵌套内部数据的场景。
1. 创建实体类
分别为甜甜圈(Donut)、面糊(Batter)、配料(Topping)创建带JPA注解的实体类,建立一对多关联:
Donut 实体类
@Entity @Table(name = "donuts") public class Donut { @Id private String id; private String type; private String name; private BigDecimal ppu; // 关联多个面糊,级联增删改 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "donut") private List<Batter> batters; // 关联多个配料,级联增删改 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "donut") private List<Topping> toppings; // 构造器、getter、setter 省略 }
Batter 实体类
@Entity @Table(name = "batters") public class Batter { @Id private String id; private String type; // 关联所属甜甜圈 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "donut_id") private Donut donut; // 构造器、getter、setter 省略 }
Topping 实体类
@Entity @Table(name = "toppings") public class Topping { @Id private String id; private String type; // 关联所属甜甜圈 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "donut_id") private Donut donut; // 构造器、getter、setter 省略 }
2. 创建Repository接口
为每个实体类创建Spring Data JPA Repository:
public interface DonutRepository extends JpaRepository<Donut, String> {} public interface BatterRepository extends JpaRepository<Batter, String> {} public interface ToppingRepository extends JpaRepository<Topping, String> {}
优势与劣势
- 优势:符合数据库范式,支持复杂查询(如筛选使用巧克力面糊的甜甜圈),数据一致性强。
- 劣势:需要维护多个实体和关联关系,存储时需处理对象间的关联绑定。
方案二:利用MySQL JSON字段存储(可选创建嵌套类)
MySQL 5.7及以上原生支持JSON类型,可直接将嵌套数据存入JSON字段,适合不需要频繁操作嵌套内部数据的场景。
方式1:直接存储JSON字符串(无需嵌套类)
仅创建Donut实体类,将batters和topping字段定义为字符串类型,指定数据库列类型为JSON:
@Entity @Table(name = "donuts") public class Donut { @Id private String id; private String type; private String name; private BigDecimal ppu; @Column(columnDefinition = "JSON") private String batters; @Column(columnDefinition = "JSON") private String toppings; // 构造器、getter、setter 省略 }
存储时需手动将嵌套对象序列化为JSON字符串,读取时再反序列化为对象,可使用Jackson或Gson工具类完成。
方式2:使用Converter自动转换(需创建嵌套类)
创建普通的嵌套类(无需@Entity注解),通过JPA Converter自动完成对象与JSON字符串的转换:
嵌套类定义
// 对应batters结构 public class Batters { private List<Batter> batter; // getter、setter 省略 } public class Batter { private String id; private String type; // getter、setter 省略 } public class Topping { private String id; private String type; // getter、setter 省略 }
创建Converter类
@Converter(autoApply = true) public class BattersConverter implements AttributeConverter<Batters, String> { private final ObjectMapper objectMapper = new ObjectMapper(); @Override public String convertToDatabaseColumn(Batters batters) { try { return objectMapper.writeValueAsString(batters); } catch (JsonProcessingException e) { throw new RuntimeException("Batters转JSON失败", e); } } @Override public Batters convertToEntityAttribute(String dbData) { try { return objectMapper.readValue(dbData, Batters.class); } catch (JsonProcessingException e) { throw new RuntimeException("JSON转Batters失败", e); } } } @Converter(autoApply = true) public class ToppingListConverter implements AttributeConverter<List<Topping>, String> { private final ObjectMapper objectMapper = new ObjectMapper(); @Override public String convertToDatabaseColumn(List<Topping> toppings) { try { return objectMapper.writeValueAsString(toppings); } catch (JsonProcessingException e) { throw new RuntimeException("Topping列表转JSON失败", e); } } @Override public List<Topping> convertToEntityAttribute(String dbData) { try { return objectMapper.readValue(dbData, new TypeReference<List<Topping>>() {}); } catch (JsonProcessingException e) { throw new RuntimeException("JSON转Topping列表失败", e); } } }
Donut实体类调整
@Entity @Table(name = "donuts") public class Donut { @Id private String id; private String type; private String name; private BigDecimal ppu; @Convert(converter = BattersConverter.class) private Batters batters; @Convert(converter = ToppingListConverter.class) private List<Topping> toppings; // 构造器、getter、setter 省略 }
优势与劣势
- 优势:无需维护多表关联,实现简单,适合快速开发和嵌套数据结构多变的场景。
- 劣势:嵌套内部数据的查询、修改性能较差,MySQL对JSON字段的索引支持有限(需通过生成列实现)。
关于是否需要为嵌套元素创建类的总结
- 若选择关系型规范存储:需要创建对应嵌套元素的实体类(带@Entity注解),建立表关联。
- 若选择JSON字段存储:
- 直接存JSON字符串:无需创建嵌套类。
- 使用Converter自动转换:需要创建普通嵌套类(无需@Entity注解),用于对象与JSON的转换。
内容的提问来源于stack exchange,提问作者Raj
相关产品推荐
相关产品推荐

