org.h2.jdb c .JdbcSQLIntegrityConstraintViolationException: нарушение ограничения ссылочной целостности - PullRequest
0 голосов
/ 14 апреля 2020

Spring boot 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 Ответ

1 голос
/ 15 апреля 2020

Вы удаляете все Orders. Из-за CascadeType.ALL это также удаляет ProductEntry для заказов. Это, в свою очередь, вызывает удаление соответствующих Product.

И это происходит по одному Orders за раз. Когда вы сталкиваетесь с первым Orders экземпляром, который ссылается на Product, на который также ссылается другой Order, вы получаете нарушение ограничения.

Если вы действительно хотите удалить все объекты, либо удалите все ProductEntry экземпляры сначала и каскадные оттуда (вручную или с использованием JPA), или используйте отложенные ограничения, если они доступны для вашей базы данных.

Если каскадная конфигурация на самом деле является ошибкой, которую я считаю вероятной, исправьте ее как минимум не включать операции удаления.

...