Java中如何返回多级结构ResultSet并转换为无冗余JSON?
解决多表关联ResultSet转多级JSON的冗余问题
核心思路
不用拆分查询,而是在遍历ResultSet时手动做内存分组聚合,把重复的主表数据合并,子表数据整理成列表,最后用JSON库序列化出目标结构。
关键前提
先修改你的SQL,必须加上im.InvoiceId作为分组唯一标识(否则无法区分不同发票):
String sql = "select im.InvoiceId, im.InvoiceDate, s.StoreId, s.StoreName, id.ItemId, id.Quantity " + "from InvoiceMaster as im " + "left join InvoiceDetail as id on id.InvoiceId = im.InvoiceId " + "left join Stores as s on s.StoreId = im.StoreId ";
步骤1:定义对应实体类
创建和目标JSON结构匹配的Java类(可以用Lombok简化getter/setter,也可手动编写):
// 发票主信息类 public class Invoice { private String invoiceDate; private Store store; private List<InvoiceDetail> invoiceDetails = new ArrayList<>(); // 手动添加getter、setter方法 } // 门店类 public class Store { private Integer storeId; private String storeName; // 手动添加getter、setter方法 } // 发票明细类 public class InvoiceDetail { private Integer itemId; private Integer quantity; // 手动添加getter、setter方法 } // 最终返回的顶层结构类 public class InvoiceResponse { private long selectTime; private List<Invoice> invoices; // 手动添加getter、setter方法 }
步骤2:遍历ResultSet并分组聚合
用Map<String, Invoice>(key为InvoiceId)缓存已处理的发票,避免重复创建对象:
// 记录查询耗时 long startTime = System.currentTimeMillis(); rs = connection.executeQuery(sql); long selectTime = System.currentTimeMillis() - startTime; Map<String, Invoice> invoiceMap = new HashMap<>(); while (rs.next()) { String invoiceId = rs.getString("InvoiceId"); // 先检查缓存中是否已有该发票 Invoice invoice = invoiceMap.get(invoiceId); if (invoice == null) { // 无缓存则创建新发票对象 invoice = new Invoice(); invoice.setInvoiceDate(rs.getString("InvoiceDate")); // 初始化门店信息 Store store = new Store(); store.setStoreId(rs.getInt("StoreId")); store.setStoreName(rs.getString("StoreName")); invoice.setStore(store); // 将新发票存入缓存 invoiceMap.put(invoiceId, invoice); } // 处理发票明细(判断非空避免空指针) if (rs.getString("ItemId") != null) { InvoiceDetail detail = new InvoiceDetail(); detail.setItemId(rs.getInt("ItemId")); detail.setQuantity(rs.getInt("Quantity")); invoice.getInvoiceDetails().add(detail); } } // 把缓存中的发票转成列表 List<Invoice> invoiceList = new ArrayList<>(invoiceMap.values()); // 封装成最终返回结构 InvoiceResponse response = new InvoiceResponse(); response.setSelectTime(selectTime); response.setInvoices(invoiceList);
步骤3:序列化生成JSON
用Jackson(Java常用JSON库)把实体类转成目标JSON:
ObjectMapper objectMapper = new ObjectMapper(); String jsonResult = objectMapper.writeValueAsString(response); // 直接返回或输出该jsonResult即可
方案优势
- 仅执行一次SQL查询,避免拆分查询带来的N+1性能问题;
- 内存分组的开销极小,可忽略不计;
- 最终生成的JSON完全符合你需要的多级嵌套结构,无冗余数据。
内容的提问来源于stack exchange,提问作者Hussain Akbar
相关产品推荐
相关产品推荐

