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
相关产品推荐
相关产品推荐

