我正在使用 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表创建成功:
我有以下控制器
@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 的发票有效负载,这导致我无法创建用户和发票类之间的关系。
{{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,但没有任何运气。
任何帮助或见解将不胜感激!
正如上面评论的,如果将 DTO 和 Entity 层分开,可能会更清晰。
用作
@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
(仅在请求正文中使用)。