You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否通过SQL JOIN查询避免JSON中的数组嵌套结构?

解决Spring关联查询返回嵌套JSON的问题

嘿,这绝对不是愚蠢的问题!很多用Spring做Web开发的小伙伴,在处理关联查询和前端数据格式匹配的时候,都会遇到类似的困扰——完全不是必然要返回嵌套结构的,咱们有好几种办法可以把数据扁平化成前端需要的单一JSON数组:

方法1:用DTO(数据传输对象)做扁平化投影

这是最规范也最常用的方案,核心思路是只返回前端需要的字段,而不是把整个实体关联结构返回。

举个例子:假设你有Order和OrderItem两个关联实体,前端需要的是包含订单ID、订单名称、商品ID、商品名称的扁平数组。你可以先创建一个对应的DTO类:

public class OrderItemFlatDTO {
    private Long orderId;
    private String orderName;
    private Long itemId;
    private String itemName;

    // 一定要和查询语句里的字段顺序匹配的有参构造函数
    public OrderItemFlatDTO(Long orderId, String orderName, Long itemId, String itemName) {
        this.orderId = orderId;
        this.orderName = orderName;
        this.itemId = itemId;
        this.itemName = itemName;
    }

    // 省略getter(如果用Lombok的@Getter会更方便)
}

然后在DAO的@Query里用构造函数投影查询:

@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
    @Query("SELECT new com.yourpackage.dto.OrderItemFlatDTO(o.id, o.name, i.id, i.name) " +
           "FROM Order o JOIN o.items i")
    List<OrderItemFlatDTO> findAllOrderItemsFlat();
}

这样返回的List<OrderItemFlatDTO>被Jackson序列化后,就是前端想要的单一扁平JSON数组啦。

方法2:用原生SQL返回Map集合

如果不想额外创建DTO类,也可以用原生SQL查询,直接返回键值对形式的Map,序列化后也是扁平结构:

@Query(value = "SELECT o.id AS order_id, o.name AS order_name, " +
               "i.id AS item_id, i.name AS item_name " +
               "FROM orders o JOIN order_items i ON o.id = i.order_id",
       nativeQuery = true)
List<Map<String, Object>> findAllOrderItemsAsFlatMap();

这种方式的好处是快速灵活,不需要额外的类,但缺点是没有类型校验,字段名要靠SQL里的别名来保证和前端需求一致。

为什么会出现嵌套结构?

顺便解释下背后的原因:你之前的关联查询返回的是Spring Data JPA的实体对象(比如包含List<OrderItem>的Order对象),Jackson默认会按照实体的关联关系序列化,把嵌套的集合也转成JSON数组,所以就出现了数组套数组的结构。咱们上面的方法本质上是跳过了实体的关联层级,直接返回扁平的数据集。

放心,这个需求完全可以实现,选哪种方法取决于你的项目规范和复杂度——DTO方案更适合长期维护,原生SQL方案适合快速临时需求。

内容的提问来源于stack exchange,提问作者Piotr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:38:11