Spring Boot结合PostgreSQL JSONB动态结构免多POJO实现方案咨询
优化实现方案
1 替换多实体为通用JSONB映射实体
完全不需要为每个JSON结构单独定义实体、UserType类,直接使用Hibernate对JSONB的原生支持,将data字段映射为通用的Jackson JsonNode 类型即可适配任意结构的JSON数据:
import com.fasterxml.jackson.databind.JsonNode; import jakarta.persistence.*; import io.hypersistence.utils.hibernate.type.json.JsonBinaryType; import org.hibernate.annotations.TypeDef; @Entity @Table(name = "information", schema = "public") @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) public class CommonInfoEntity { @Id private Integer id; @Type(type = "jsonb") @Column(columnDefinition = "jsonb") private JsonNode data; // 通用getter/setter public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public JsonNode getData() { return data; } public void setData(JsonNode data) { this.data = data; } }
依赖说明:Hibernate 6+自带JSON类型支持无需额外引入依赖;Hibernate 5版本需引入hypersistence-utils依赖:
<dependency> <groupId>io.hypersistence</groupId> <artifactId>hypersistence-utils-hibernate-55</artifactId> <version>3.7.0</version> </dependency>
2 业务层实现类型自动匹配
如果部分固定JSON结构需要对应POJO做业务逻辑处理,可在Service层根据id或者JSON内的标识字段自动做类型转换:
import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class CommonInfoService { @Autowired private CommonInfoRepository infoRepository; @Autowired private ObjectMapper objectMapper; // 通用查询方法,自动匹配对应POJO public Object getInfoById(Integer id) { CommonInfoEntity entity = infoRepository.findById(id).orElseThrow(); // 可根据id或者JSON内的name字段匹配对应类型 String userName = entity.getData().get("name").asText(); return switch (userName) { case "AlexRob" -> objectMapper.convertValue(entity.getData(), AlexRob.class); case "Janice" -> objectMapper.convertValue(entity.getData(), Janice.class); default -> entity.getData(); // 未知结构直接返回原始JSON }; } // 通用保存方法 public CommonInfoEntity saveInfo(Integer id, Object data) { CommonInfoEntity entity = new CommonInfoEntity(); entity.setId(id); entity.setData(objectMapper.valueToTree(data)); return infoRepository.save(entity); } }
3 统一控制器实现
仅需要一个控制器即可处理所有id的存取请求:
import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/info") public class CommonInfoController { @Autowired private CommonInfoService infoService; @GetMapping("/{id}") public Object getInfo(@PathVariable Integer id) { return infoService.getInfoById(id); } @PostMapping("/{id}") public CommonInfoEntity saveInfo(@PathVariable Integer id, @RequestBody Object data) { return infoService.saveInfo(id, data); } }
该方案后续新增JSON结构仅需要新增对应POJO、在Service层加类型分支即可,无需修改底层实体、控制器代码,冗余度极低。
内容的提问来源于stack exchange,提问作者Deepak Yadav
相关产品推荐
相关产品推荐

