我收到此主键约束错误
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.dao.DataIntegrityViolationException: could not execute statement [Unique index or primary key violation: "PUBLIC.CONSTRAINT_INDEX_3 ON PUBLIC.USER_TACO_ORDER_REF(TACO_ORDER_ID NULLS FIRST) VALUES ( /* 1 */ '52aca972-aeac-4305-9021-ad17ea1a0b07' )"; SQL statement:
insert into user_taco_order_ref (user_id,taco_order_id) values (?,?) [23505-220]] [insert into user_taco_order_ref (user_id,taco_order_id) values (?,?)]; SQL [insert into user_taco_order_ref (user_id,taco_order_id) values (?,?)]; constraint ["PUBLIC.CONSTRAINT_INDEX_3 ON PUBLIC.USER_TACO_ORDER_REF(TACO_ORDER_ID NULLS FIRST) VALUES ( /* 1 */ '52aca972-aeac-4305-9021-ad17ea1a0b07' )"
我在一个会话中保存多个 TacoOrder 对象。在一阶控制器中工作正常。它保存在数据库中并且没有错误。之后,我将其添加到用户的 tacoOrder 列表集合中,并作为 Cascade.ALL 自动保存。数据库每次都会重置,因此它只是列表中的一个对象。
在第二个订单中,我重置当前会话 TacoOrder 对象,它通过相同的控制器并添加到用户列表中,并且当休眠保留用户时。该列表也被持久化,但它现在有 2 个 tacoOrders,其中之一已经被持久化,保存这给了我错误。
这些是控制器和实体
@Transactional
@PostMapping("/current")
public String processOrder(@ModelAttribute("order") @Valid TacoOrder order, Errors errors,
@AuthenticationPrincipal User user) {
if(errors.hasErrors()){
return "orderForm";
}
order.setUser(user);
order.setPlacedAt(new Date());
user.addTacoOrder(order);
log.info("4 {} {}", order, user); //LOG
TacoOrder tacoOrder = orderRepository.save(order);
userService.updateUserFromOrder(user, tacoOrder);
userRepository.save(user);
log.info("Order submitted: {}", tacoOrder); //LOG
return "redirect:/orders";
}
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(
name = "User_Taco_Order_Ref",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "tacoOrder_id"))
private List<TacoOrder> tacoOrders = new ArrayList<>();
这些是日志:- 第一订单:
4 TacoOrder(id=52aca972-aeac-4305-9021-ad17ea1a0b07, placedAt=Fri Mar 29 04:07:34 IST 2024, deliveryName=a, deliveryStreet=a, deliveryCity=a, deliveryState=a, deliveryZip=a, ccNumber=4417123456789113, ccExpiration=11/2024, ccCVV=111, tacos=[Taco(id=1, createdAt=Fri Mar 29 04:07:24 IST 2024, name=Classic Beef Taco, ingredients=[Ingredient(id=FLTO, name=Flour Tortilla, type=WRAP), Ingredient(id=GRBF, name=Ground Beef, type=PROTEIN), Ingredient(id=CHED, name=Cheddar, type=CHEESE), Ingredient(id=LETC, name=Lettuce, type=VEGGIES), Ingredient(id=SLSA, name=Salsa, type=SAUCE)])])
User(id=1, username=admin, password=$2a$10$zpjL0V253nLpa1cH0j5sNOWKrfyikWjMZcXzc1TQ5HtttSgQgGi7O, roles=[ROLE_USER, ROLE_ADMIN], fullName=null, street=null, city=null, state=null, zip=null, phoneNumber=null, tacoOrders=[TacoOrder(id=52aca972-aeac-4305-9021-ad17ea1a0b07, placedAt=Fri Mar 29 04:07:34 IST 2024, (rest is same)
第二个命令:
4 TacoOrder(id=37808e6b-ed1d-4f38-8652-8c672b88d5e5, placedAt=Fri Mar 29 04:07:52 IST 2024, deliveryName=1, deliveryStreet=1, deliveryCity=1, deliveryState=1, deliveryZip=1, ccNumber=4417123456789113, ccExpiration=11/2024, ccCVV=111, tacos=[Taco(id=2, createdAt=Fri Mar 29 04:07:39 IST 2024, name=Spicy Carnitas Delight, ingredients=[Ingredient(id=COTO, name=Corn Tortilla, type=WRAP), Ingredient(id=CARN, name=Carnitas, type=PROTEIN), Ingredient(id=JALA, name=Jalapeños, type=VEGGIES), Ingredient(id=LETC, name=Lettuce, type=VEGGIES), Ingredient(id=SLSA, name=Salsa, type=SAUCE)])])
User(id=1, username=admin, password=$2a$10$zpjL0V253nLpa1cH0j5sNOWKrfyikWjMZcXzc1TQ5HtttSgQgGi7O, roles=[ROLE_USER, ROLE_ADMIN], fullName=null, street=a, city=a, state=a, zip=a, phoneNumber=null, tacoOrders=[TacoOrder(id=52aca972-aeac-4305-9021-ad17ea1a0b07, placedAt=Fri Mar 29 04:07:34 IST 2024,
, TacoOrder(id=37808e6b-ed1d-4f38-8652-8c672b88d5e5, placedAt=Fri Mar 29 04:07:52 IST 2024,
根据日志,第一顺序@id是
52aca972-aeac-4305-9021-ad17ea1a0b07
第二阶@id是
37808e6b-ed1d-4f38-8652-8c672b88d5e5
现在在第二个订单中,用户同时拥有第一个订单(已保存在 User_Taco_Order_Ref 表中)和尚未添加到 User_Taco_Order_Ref 表中的第二个新订单。 Hibernate 再次保存整个集合,并在保存已经持久保存的 taco 订单实例时给出此错误。 我该如何解决它?
错误是由于 USER 实体中 tacoOrder 列表上的 @JoinTable 注释造成的。 通过使用mappedBy,我们删除了这个额外的表,因为在OneToMany关系上使用joinTable是相当不常见的,并且hibernate不会再次添加已经持久化的实体。