Springboot 3 ManytoMany 请求有效负载正确序列化

问题描述 投票:0回答:1

我正在使用 Spring Boot 3、Java 21 Restful API 和 JPA 与 mysql,但在接收请求时遇到问题。

我正在与模型

User
Invoice
建立多对多关系,如下所示:

用户

@Data
@NoArgsConstructor
@Entity(name = "users")
public class User extends Audit {
    ....
    @JsonIgnoreProperties({"users", "handler", "hibernateLazyInitializer"})
    @ManyToMany
    @JoinTable(
        name = "users_invoices",
        joinColumns = @JoinColumn(name="user_id"),
        inverseJoinColumns = @JoinColumn(name="invoice_id"),
        uniqueConstraints = { @UniqueConstraint(columnNames = {"user_id", "invoice_id"})}
    )
    private List<Invoice> invoices;

    .....
}

发票

@Data
@NoArgsConstructor
@Entity(name = "invoices")
public class Invoice extends Audit {
    
    ....

    @JsonIgnoreProperties({"invoices", "handler", "hibernateLazyInitializer"})
    @ManyToMany(mappedBy = "invoices")
    private List<User> users;

    ....
}

MySQL表创建成功:

  • users table img
  • invoices table img
  • users invoices table img

我有以下控制器

@RestController
@RequestMapping("/invoices")
public class InvoiceController {
    ....
    
    @PostMapping("")
    @Transactional
    public Invoice saveInvoice(@RequestBody Invoice invoice){
        System.out.println(invoice.toString());
        Invoice newInvoice = invoiceService.createInvoice(invoice);
        return newInvoice;
    }
}

我期望发生的情况:user_id 或用户对象根据我对端点的请求进行序列化。

发生了什么:当到达我的端点时,我收到了没有 user_id 的发票有效负载,这导致我无法创建用户和发票类之间的关系。

我的邮递员请求正文如下Postman Request img(其中

{{id}}
是我的UUID(如果是用户):

{
    "user_id":  "{{id}}",
    "amount": 1150,
    "status": "PENDING"
}

收到请求正文时,我得到以下对象:

Invoice(id=null, users=null, amount=1150, status=PENDING, date=null)

我尝试更改请求正文以获得用户对象

"user_id": [Object user]
,并且还更改了
"users": ["{{id}}"]
的user_id,但没有任何运气。

任何帮助或见解将不胜感激!

java mysql spring-boot jpa
1个回答
0
投票

正如上面评论的,如果将 DTO 和 Entity 层分开,可能会更清晰。

发票DTO

用作

@RequestBody
:

public class InvoiceDTO {
    // getters/setters/constructors
    private long amount;
    private List<Long> userIds;
    ...
}

发票

public void addUser(User user) {
    users.add(user);
    user.getInvoices().add(this);
}

发票服务

@Transactional
public Invoice saveInvoice(InvoiceDTO invoiceDto) {
    Invoice invoice = new Invoice();
    invoice.setAmount(invoiceDto.getAmount());
    invoice.setUsers(new ArrayList<>());
    List<User> users = userRepository.findAllById(invoiceDTO.getUserIds());
    for(User user : users) {
        invoice.addUser(user);
    }
    return invoiceRepository.save(invoice);
}

这应该与请求正文一起使用

{
    "userIds":  [1,2,3],
    "amount": 1150,
    ...
}

您需要解决潜在的循环依赖/延迟初始化/事务问题。有关更多详细信息,我建议您查阅 Vlad Mihalcea 的这篇博文

您可以在不引入 InvoiceDTO 的情况下使其工作 - 但随后您会例如需要在不保存到数据库的发票字段上添加

@Transient
(仅在请求正文中使用)。

© www.soinside.com 2019 - 2024. All rights reserved.