Spring Data R2DBC 中嵌套 JSON 对象的通用映射方案

胖墨君_4420

胖墨君_4420

2026-08-08

509人浏览

原创

Spring Data R2DBC 中嵌套 JSON 对象的通用映射方案

本文介绍一种无需为每个嵌套结构重复编写自定义 Converter 的通用方式,利用 PostgreSQL 的 Json 类型配合 ObjectMapper 实现灵活、可复用的 JSON 反序列化,兼顾响应式编程特性与开发效率。

本文介绍一种无需为每个嵌套结构重复编写自定义 converter 的通用方式,利用 postgresql 的 `json` 类型配合 objectmapper 实现灵活、可复用的 json 反序列化,兼顾响应式编程特性与开发效率。

在 Spring Data R2DBC 中,原生不支持如 JPA 那样的深度对象图映射(例如 @Embedded 或嵌套实体自动展开),尤其当数据库字段存储的是 JSON 字符串(如 PostgreSQL 的 JSONB 类型)时,框架无法自动将其反序列化为 Java 嵌套对象。但通过合理分层设计与类型抽象,完全可以避免“为每个实体写一个 @ReadingConverter”的冗余模式。

✅ 推荐方案:io.r2dbc.postgresql.codec.Json + 函数式映射

核心思路是延迟解析、按需转换:不在 RowMapper 或 Converter 层硬编码目标类型,而是将原始 JSON 数据以类型安全的 Json 对象保留,再在 Service 或 DTO 转换层统一处理。

1. 实体类使用 Json 类型(PostgreSQL 专用)

@Table("my_table")
@Data
@Builder
public class MyObject {
    @Id
    private Integer id;
    // 直接映射为 R2DBC PostgreSQL 提供的 Json 类型
    private Json data; // 自动绑定 JSONB 字段,不触发提前解析
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

⚠️ 注意:Json 类型仅适用于 r2dbc-postgresql。若使用其他数据库(如 H2、MySQL),需改用 String 并自行处理空值/转义。

jm-jsjkxyjs02-zlm-405
jm-jsjkxyjs02-zlm-405

使用约定式提交(Conventional Commits)生成标准化的 Git 提交信息。适用于以下场景: (1) 暂存更改时需要提交信息; (2) 审查 diff 时希望获得结构化摘要; (3) 编写 PR 描述或变更日志(changelog)条目; (4) 用户明确要求“为本次更改编写提交信息”。 该功能会分析已暂存/未暂存的 diff,并生成按类型(type)划分范围的提交信息。

下载

2. 定义灵活的 DTO 与嵌套模型

@Data
@Builder
public class MyObjectDTO {
    private Integer id;
    private YourNestedObjectType data; // 可任意替换为具体业务类
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

// 支持任意嵌套结构(含 List、Map、自定义对象)
public class YourNestedObjectType {
    private String field1;
    private List<otherobject> otherObjects;
    private Map<string bigdecimal> metrics;
}</string></otherobject>

3. 统一映射工具(泛型 + 函数式)

避免重复 try-catch 和 ObjectMapper 实例化,封装为可复用方法:

@Component
public class JsonMapper {

    private final ObjectMapper objectMapper = new ObjectMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        .registerModule(new JavaTimeModule());

    public <t> T fromJson(Json json, Class<t> targetType) {
        if (json == null || json.isNull()) {
            return null;
        }
        try {
            return objectMapper.readValue(json.asString(), targetType);
        } catch (JsonProcessingException e) {
            throw new IllegalArgumentException(
                "Failed to deserialize JSON field to " + targetType.getSimpleName(), e);
        }
    }

    // 示例:转换为 DTO(推荐在 Service 层调用)
    public MyObjectDTO toDto(MyObject entity) {
        return MyObjectDTO.builder()
            .id(entity.getId())
            .data(fromJson(entity.getData(), YourNestedObjectType.class))
            .createdAt(entity.getCreatedAt())
            .updatedAt(entity.getUpdatedAt())
            .build();
    }
}</t></t>

4. 在 Repository 或 Service 中使用(响应式友好)

@Repository
public class MyObjectRepository {

    private final Database database;
    private final JsonMapper jsonMapper;

    public MyObjectRepository(Database database, JsonMapper jsonMapper) {
        this.database = database;
        this.jsonMapper = jsonMapper;
    }

    public Flux<myobjectdto> findAllAsDto() {
        return database
            .execute("SELECT * FROM my_table")
            .map(row -> {
                MyObject entity = new MyObject();
                entity.setId(row.get("id", Integer.class));
                entity.setData(row.get("data", Json.class)); // ← 关键:保持 Json 类型
                entity.setCreatedAt(row.get("created_at", LocalDateTime.class));
                entity.setUpdatedAt(row.get("updated_at", LocalDateTime.class));
                return entity;
            })
            .map(jsonMapper::toDto); // ← 统一转换入口
    }
}</myobjectdto>

? 优势总结

  • ✅ 真正通用:fromJson(Json, Class) 方法可复用于任意嵌套类型,无需新增 Converter;
  • ✅ 解耦清晰:数据访问层(Entity)与领域模型(DTO/VO)分离,符合响应式分层架构;
  • ✅ 错误可控:JSON 解析异常在业务层捕获并转化为语义明确的 IllegalArgumentException,便于监控与重试;
  • ✅ 性能合理:仅在必要时解析(非每行都触发),且 Json.asString() 是轻量操作;
  • ✅ 兼容扩展:未来若需支持 MongoDB 或其它 JSON 存储,只需替换 Json 抽象层。

⚠️ 注意事项

  • 若使用非 PostgreSQL 数据库,请将 private Json data 替换为 private String data,并在 fromJson 中增加 null/空字符串校验;
  • ObjectMapper 应单例复用(如上例中 @Component 管理),避免频繁创建影响性能;
  • 对高频调用场景,可考虑对常用类型(如 YourNestedObjectType)做 TypeReference 缓存,进一步优化反射开销;
  • 不建议在 @ReadingConverter 中直接调用 ObjectMapper —— 它会破坏 R2DBC 的类型推导链,且难以泛型化。

通过该方案,你既保住了 R2DBC 的非阻塞优势,又获得了接近 JPA 的开发体验:一次封装,处处复用,嵌套无忧。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

js json

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

2025.08.06

2851

22

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

2026.01.26

517

25

spring boot框架优点
spring boot框架优点

spring boot框架的优点有简化配置、快速开发、内嵌服务器、微服务支持、自动化测试和生态系统支持。本专题为大家提供spring boot相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.05

691

5

spring框架有哪些
spring框架有哪些

spring框架有Spring Core、Spring MVC、Spring Data、Spring Security、Spring AOP和Spring Boot。详细介绍:1、Spring Core,通过将对象的创建和依赖关系的管理交给容器来实现,从而降低了组件之间的耦合度;2、Spring MVC,提供基于模型-视图-控制器的架构,用于开发灵活和可扩展的Web应用程序等。

2023.10.12

1455

7

Java Spring Boot开发
Java Spring Boot开发

本专题围绕 Java 主流开发框架 Spring Boot 展开,系统讲解依赖注入、配置管理、数据访问、RESTful API、微服务架构与安全认证等核心知识,并通过电商平台、博客系统与企业管理系统等项目实战,帮助学员掌握使用 Spring Boot 快速开发高效、稳定的企业级应用。

2025.08.19

5506

10

Java Spring Boot 4更新教程_Java Spring Boot 4有哪些新特性
Java Spring Boot 4更新教程_Java Spring Boot 4有哪些新特性

Spring Boot 是一个基于 Spring 框架的 Java 开发框架,它通过 约定优于配置的原则,大幅简化了 Spring 应用的初始搭建、配置和开发过程,让开发者可以快速构建独立的、生产级别的 Spring 应用,无需繁琐的样板配置,通常集成嵌入式服务器(如 Tomcat),提供“开箱即用”的体验,是构建微服务和 Web 应用的流行工具。

2025.12.22

436

5

Java Spring Boot 微服务实战
Java Spring Boot 微服务实战

本专题深入讲解 Java Spring Boot 在微服务架构中的应用,内容涵盖服务注册与发现、REST API开发、配置中心、负载均衡、熔断与限流、日志与监控。通过实际项目案例(如电商订单系统),帮助开发者掌握 从单体应用迁移到高可用微服务系统的完整流程与实战能力。

2025.12.24

680

18

Spring Boot企业级开发与MyBatis Plus实战
Spring Boot企业级开发与MyBatis Plus实战

本专题面向 Java 后端开发者,系统讲解如何基于 Spring Boot 与 MyBatis Plus 构建高效、规范的企业级应用。内容涵盖项目架构设计、数据访问层封装、通用 CRUD 实现、分页与条件查询、代码生成器以及常见性能优化方案。通过完整实战案例,帮助开发者提升后端开发效率,减少重复代码,快速交付稳定可维护的业务系统。

2026.02.11

405

24

Kotlin协程编程与Spring Boot集成实践
Kotlin协程编程与Spring Boot集成实践

本专题围绕 Kotlin 协程机制展开,深入讲解挂起函数、协程作用域、结构化并发与异常处理机制,并结合 Spring Boot 展示协程在后端开发中的实际应用。内容涵盖异步接口设计、数据库调用优化、线程资源管理以及性能调优策略,帮助开发者构建更加简洁高效的 Kotlin 后端服务架构。

2026.02.12

391

18

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 21.3万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 4.9万人学习