org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException:违反参照完整性约束

Posted

技术标签:

【中文标题】org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException:违反参照完整性约束【英文标题】:org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Referential integrity constraint violation 【发布时间】:2020-04-14 20:59:56 【问题描述】:

春季启动 2.5

@Entity
public class Orders 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @NotNull
    @DateTimeFormat(pattern = "dd.MM.yyyy HH:mm:ss")
    private Date created;
    private String paymentCardNumber;
    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "shipping_id")
    private Shipping shipping;
    private String promoCode;
    @NotNull
    private double totalAmount;
    @NotNull
    private String currenty;
    @NotNull
    @OneToMany(mappedBy = "orders", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<ProductEntry> productEntities = new HashSet<>();


  public void addProduct(Product product, int quantity) 
        productEntities.add(new ProductEntry(product, quantity, this));
    


@Entity
public class ProductEntry 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Exclude
    private int id;
    @NotNull
    @DateTimeFormat(pattern = "dd.MM.yyyy HH:mm:ss")
    @Exclude
    private Date created;
    @DateTimeFormat(pattern = "dd.MM.yyyy HH:mm:ss")
    @Exclude
    private Date updated;
    private int quantity;
    @OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Product product;
    @Exclude
    @ManyToOne(fetch = FetchType.LAZY)
    private Orders orders;
    @Exclude
    @ManyToOne(fetch = FetchType.EAGER)
    private Cart cart;@Entity


public class Product 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @NotNull
    private String name;
    private String description;
    @NotNull
    @DateTimeFormat(pattern = "dd.MM.yyyy HH:mm:ss")
    private Date created;
    @DateTimeFormat(pattern = "dd.MM.yyyy HH:mm:ss")
    private Date updated;
    @NotNull
    private double price;
    @NotNull
    private String currency;
    @ElementCollection
    private Set<String> images;
    @Exclude
    @OneToOne(mappedBy = "product", fetch = FetchType.EAGER)
    private ProductEntry productEntry;

我通过这种方法成功创建订单:

@PostMapping("/order/cart")
public Response createOrderByCart(@RequestBody Map<String, Object> payloadMap) 
    int cartId = (int) payloadMap.get("cart_id");
    Optional<Cart> findCart = cartRepository.findById(cartId);
    if (findCart.isPresent()) 
        final Orders order = new ObjectMapper().convertValue(payloadMap.get("order"), Orders.class);
        order.setCreated(new Date());
        Cart cart = findCart.get();
        Set<ProductEntry> productEntitiesInCartSet = cart.getProductEntities();
        for (ProductEntry productEntry : productEntitiesInCartSet) 
            order.addProduct(productEntry.getProduct(), productEntry.getQuantity());
        
        double orderTotalAmount = cart.getTotalAmount();
        if (order.getPromoCode() != null && orderTotalAmount > PROMO_CODE_DISCOUNT_AMOUNT) 
            orderTotalAmount = orderTotalAmount - PROMO_CODE_DISCOUNT_AMOUNT;
        
        order.setTotalAmount(orderTotalAmount);
        order.setCurrenty(cart.getCurrency());
        ordersRepository.save(order);
        return ResponseService.getSuccessResponse(GsonUtil.gson.toJson(order));
     else 
        String errorMessage = "Not found cart with id " + cartId;
        logger.warn(errorMessage);
        return ResponseService.getErrorResponse(errorMessage);
    

但在我尝试通过以下方式删除订单后:

@DeleteMapping("/orders")
    public Response deleteAllOrders() 
        logger.info("deleteAllOrders: ");
        ordersRepository.deleteAll();
        logger.info("deleteAllOrders: success_delete_all_orders");
        return ResponseService.getSuccessResponse();
    

我在这一行得到错误:

ordersRepository.deleteAll();

错误:

delete from product where id=? [23503-200]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause

org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Referential integrity constraint violation: "FKEWQ69R22L90CKJDKN8TTVB7J3: PUBLIC.PRODUCT_ENTRY FOREIGN KEY(PRODUCT_ID) REFERENCES PUBLIC.PRODUCT(ID) (3)"; SQL statement:
delete from product where id=? [23503-200]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:459) ~[h2-1.4.200.jar:1.4.200]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:429) ~[h2-1.4.200.jar:1.4.200]
    at org.h2.message.DbException.get(DbException.java:205) ~[h2-1.4.200.jar:1.4.200]
    at org.h2.message.DbException.get(DbException.java:181) ~[h2-1.4.200.jar:1.4.200]
    at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:373) ~[h2-1.4.200.jar:1.4.200]
    at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:390) ~[h2-1.4.200.jar:1.4.200]
    at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:265) ~[h2-1.4.200.jar:1.4.200]
    at org.h2.table.Table.fireConstraints(Table.java:1057) ~[h2-1.4.200.jar:1.4.200]
    at org.h2.table.Table.fireAfterRow(Table.java:1075) ~[h2-1.4.200.jar:1.4.200]
    at org.h2.command.dml.Delete.update(Delete.java:153) ~[h2-1.4.200.jar:1.4.200]
    at org.h2.command.CommandContainer.update(CommandContainer.java:198) ~[h2-1.4.200.jar:1.4.200]
    at org.h2.command.Command.executeUpdate(Command.java:251) ~[h2-1.4.200.jar:1.4.200]
    at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:191) ~[h2-1.4.200.jar:1.4.200]
    at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:152) ~[h2-1.4.200.jar:1.4.200]
    at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61) ~[HikariCP-3.4.2.jar:na]

【问题讨论】:

【参考方案1】:

您正在删除所有Orders。 由于CascadeType.ALL,这也会删除订单的ProductEntry。 这反过来又会触发删除相应的Product

这种情况一次发生一个Orders。 当您遇到第一个引用 ProductOrders 实例时,该实例也被另一个 Order 引用,您会遇到约束冲突。

如果您确实想删除所有实体,请先删除所有 ProductEntry 实例并从那里级联(手动或使用 JPA),或者使用延迟约束(如果它们可用于您的数据库)。

如果级联配置实际上是一个错误,我认为这很可能,请将其修复为至少不包括删除操作。

【讨论】:

我需要 CascadeType.ALL,因为我还将许多产品添加到购物车。如果删除 CascadeType.ALL 则不会插入许多产品到购物车。 然后使用您实际需要的CascadeType 值。不止ALL 或者什么都没有。 这个帮助:cascade = CascadeType.PERSIST。谢谢

以上是关于org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException:违反参照完整性约束的主要内容,如果未能解决你的问题,请参考以下文章