保存含嵌套对象的JSON至数据库时遇NonUniqueResultException错误求助
问题分析与解决方案
1. 异常直接原因:查询返回非唯一结果
NonUniqueResultException的核心原因是:
你用Optional<Debts>和Optional<Madeen>接收查询结果,但debtsRepository.findDebtsByPersonIdAndOrganization_id或madeenRepository.findByPersonId实际返回了2条数据。Optional仅支持0或1条结果,超出范围就会抛出异常。
修复方案:
- 如果业务逻辑允许多条结果:将查询方法的返回类型改为
List<Debts>/List<Madeen>,对应代码中用List接收。 - 如果业务逻辑要求唯一结果:检查数据库中是否存在重复数据,或者修改查询条件(比如添加唯一约束字段),或改用
findFirstByXXX类方法确保只返回第一条结果。
2. DTO设计错误:无法正确解析JSON数组
你的InvoicesDTO实现了List<InvoicesDTO>,这是完全错误的设计——这个类是单个发票项的DTO,不应该继承List接口。同时InvoiceDTO中用private InvoicesDTO invoices;无法正确接收JSON中的数组,会导致序列化/反序列化失败,也会影响后续遍历逻辑。
修复方案:
- 重命名
InvoicesDTO为InvoiceItemDTO(语义更准确),移除implements List<InvoicesDTO>。 - 在
InvoiceDTO中将invoices字段改为List<InvoiceItemDTO>类型,用于接收JSON数组。
修正后的代码示例:
InvoiceItemDTO
@Getter @Setter @AllArgsConstructor @NoArgsConstructor public class InvoiceItemDTO { @NotNull(message = "invoice Number can't be null") private String invoiceNumber; @NotNull(message = "invoiceAmount can't be null") private Double invoiceAmount; }
InvoiceDTO
@Getter @Setter @NoArgsConstructor @AllArgsConstructor public class InvoiceDTO { @NotNull(message = "PersonId can't be null") @PersonId private String personId; @NotNull(message = "invoiceDate can't be null") @PastOrPresent @JsonFormat(pattern = "yyyy-MM-dd") private LocalDate invoiceDate; private List<InvoiceItemDTO> invoices; // 改为List类型接收数组 }
3. 处理逻辑优化
修复DTO后,调整处理逻辑,同时增加空值判断避免空指针:
try { // 根据业务选择合适的查询返回类型 List<Debts> debtsList = debtsRepository.findDebtsByPersonIdAndOrganization_id(invoiceDTO.getPersonId(), organization.get().getId()); List<Madeen> madeenList = madeenRepository.findByPersonId(invoiceDTO.getPersonId()); List<InvoiceItemDTO> invoicesDTO = invoiceDTO.getInvoices(); // 增加空值判断 if (invoicesDTO != null && !invoicesDTO.isEmpty()) { for (InvoiceItemDTO invoiceItem : invoicesDTO) { Debts newDebt = new Debts(); newDebt.setPersonId(invoiceDTO.getPersonId()); newDebt.setCreatedDate(LocalDate.now()); newDebt.setUpdatedDate(invoiceDTO.getInvoiceDate()); newDebt.setDebtAmount(invoiceItem.getInvoiceAmount()); newDebt.setInvoiceNumber(invoiceItem.getInvoiceNumber()); // 先判断organization是否存在,避免NoSuchElementException if (organization.isPresent()) { newDebt.setOrganization(organization.get()); debtsRepository.save(newDebt); } } } } catch (Exception e) { // 按需处理异常,比如日志记录、返回错误响应 }
内容的提问来源于stack exchange,提问作者TechNewPy
相关产品推荐
相关产品推荐

