Когда я пытаюсь удалить объект с помощью Hibernate, не появляется сообщение об ошибке, но не удаляется - PullRequest
0 голосов
/ 30 марта 2019

У меня есть три сущности, Bag, Item и Category.Один Bag может иметь множество Items, а многие Items могут иметь множество Categories:

Bag <---- <code>OneToMany ----> Item

Item ----- ManyToMany -----> Category

Нет необходимости хранить items в Category

Когда яПопробуйте удалить Item без categories, сообщения об ошибке нет, но Item не удалено.Однако, если я пытаюсь удалить тот же item в базе данных, он удаляется успешно.

С другой стороны, если я пытаюсь удалить Item с categories, я получаю это сообщение об ошибке:

"Невозможно удалить или обновить родительскую строку: сбой ограничения внешнего ключа (item_categories, CONSTRAINT fk_item_categories_items_id FOREIGN KEY (items_id) ССЫЛКИ item (id))".

Я бы хотел удалить item и связь с его categories, но сохранить categories.Как я мог это сделать?

Для первой проблемы я попытался добавить к методу удаления bag.removeItems(item), но он только удаляет связь между обоими, и item продолжается в БД.

Bag.java

    @OneToMany(mappedBy = "bag", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
    @JsonIgnoreProperties("bag")
    private Set<Item> items = new HashSet<>();

Item.java

    @ManyToOne
    @JsonIgnoreProperties("items")
    private Bag bag;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "item_categories",
               joinColumns = @JoinColumn(name="items_id", referencedColumnName="id"),
               inverseJoinColumns = @JoinColumn(name="categories_id", referencedColumnName="id"))
    private Set<Category> categories = new HashSet<>();

ItemResource.java

    @DeleteMapping("/items/{id}")
    @Timed
    public ResponseEntity<Void> deleteItem(@PathVariable Long id) {
        itemRepository.delete(id);
        return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build();
    }

РЕДАКТИРОВАТЬ: Методы создания и обновления отлично работает.

1 Ответ

0 голосов
/ 30 марта 2019

Таким образом, проблема в том, что у вас есть отношение «многие ко многим», которое решается с помощью промежуточной таблицы (или ассоциации), где хранятся пары «элемент - категория». При удалении элемента выполняется фактический запрос DELETE FROM item, но он не выполняется, поскольку существует ограничение внешнего ключа, которое не позволяет соответствующим парам оставаться потерянными.

Чтобы решить эту проблему, вы можете просто удалить ассоциации:

item.getCategories().clear();

Относительно того, где должен выполняться этот код, решать только вам. Вы можете создать крючок внутри Item, например, так:

@PreRemove
private void deleteCategories() {
    this.getCategories().clear();
}

Или вы можете создать ItemService, который будет делать что-то вроде

public void deleteItem(Long id) {
    final Item item = itemRepository.findById(id);
    // you can handle here when not found, which is a good thing to do
    item.getCategories().clear();
    itemRepository.deleteItem(item);
}

Или вы можете реализовать собственный метод для репозитория JPA, который мне не нравится, но вы можете прочитать об этом здесь Как добавить собственный метод в Spring Data JPA .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...