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

Spring Boot原生SQL用OUTER APPLY返回无列名 如何适配React读取

解决方案

方案1:后端改造返回带列名的JSON(推荐)

你当前返回纯数组结构的原因是createNativeQuery默认返回List<Object[]>,没有做字段映射,序列化后自然没有列名。有两种简便改造方式:

子方案1.1 结果集映射到Client实体

先在Client实体类上添加结果集映射注解:

@SqlResultSetMapping(
    name = "ClientWithPaymentMapping",
    classes = @ConstructorResult(
        targetClass = Client.class,
        columns = {
            @ColumnResult(name = "CustomerNumber", type = String.class),
            @ColumnResult(name = "Name", type = String.class),
            @ColumnResult(name = "Surname", type = String.class),
            @ColumnResult(name = "Area", type = String.class),
            @ColumnResult(name = "City", type = String.class),
            @ColumnResult(name = "Address", type = String.class),
            @ColumnResult(name = "Enabled", type = String.class),
            @ColumnResult(name = "CustomerTypeID", type = Integer.class),
            @ColumnResult(name = "DateCreated", type = Date.class),
            @ColumnResult(name = "Debit", type = BigDecimal.class),
            @ColumnResult(name = "Credit", type = BigDecimal.class)
        }
    )
)
@Entity
public class Client {
    // 原有实体字段、构造方法、get/set保持不变
}

修改接口查询代码,指定映射规则:

@GetMapping
public List<Client> getClients()
{
    List<Client> results = entityManager.createNativeQuery("SELECT top 17 c.CustomerNumber, c.Name, c.Surname, c.Area, c.City, c.Address, c.Enabled, c.CustomerTypeID, c.DateCreated, p.Debit, p.Credit\n" +
                    "FROM tblCustomer c OUTER APPLY\n" +
                    "     (SELECT TOP (1) p.*\n" +
                    "      FROM tblPayments p\n" +
                    "      WHERE c.CustomerNumber = p.CustomerNumber\n" +
                    "      ORDER BY p.id DESC\n" +
                    "     ) p;", "ClientWithPaymentMapping")
            .getResultList();
    return results;
}

子方案1.2 直接返回Map结构(无需修改实体)

如果不想写映射规则,可以直接把查询结果转为键值对Map,序列化后自动带列名:

@GetMapping
public List<Map<String, Object>> getClients()
{
    List<Map<String, Object>> results = entityManager.createNativeQuery("SELECT top 17 c.CustomerNumber, c.Name, c.Surname, c.Area, c.City, c.Address, c.Enabled, c.CustomerTypeID, c.DateCreated, p.Debit, p.Credit\n" +
                    "FROM tblCustomer c OUTER APPLY\n" +
                    "     (SELECT TOP (1) p.*\n" +
                    "      FROM tblPayments p\n" +
                    "      WHERE c.CustomerNumber = p.CustomerNumber\n" +
                    "      ORDER BY p.id DESC\n" +
                    "     ) p;")
            .unwrap(org.hibernate.query.NativeQuery.class)
            .setResultTransformer(org.hibernate.transform.AliasToEntityMapResultTransformer.INSTANCE)
            .getResultList();
    return results;
}

方案2:前端直接处理无列名数组

如果不需要改造后端,可以在React侧按照SQL查询的列顺序,手动映射为带字段名的对象:

// 字段顺序必须和SQL里SELECT的列顺序完全一致
const FIELD_ORDER = [
  'customerNumber', 'name', 'surname', 'area', 'city', 'address',
  'enabled', 'customerTypeId', 'dateCreated', 'debit', 'credit'
]

// 接口请求完成后转换数据
const fetchClientData = async () => {
  const res = await fetch('http://localhost:8080/api/v1/client')
  const rawData = await res.json()
  // 转换为带字段名的对象数组
  const clientList = rawData.map(row => {
    return row.reduce((obj, value, index) => {
      obj[FIELD_ORDER[index]] = value
      return obj
    }, {})
  })
  // 后续可以正常使用clientList渲染页面
}

内容的提问来源于stack exchange,提问作者Qëndrim Izairi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 01:54:03