Hibernate OnDelete каскад в тесте не работает - PullRequest
1 голос
/ 13 июня 2019

У меня есть однонаправленные связанные объекты:

@Entity
public class Book {
    private String isbn;
}

@Entity
private class Recommentation {
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "book_id", nullable = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    private Book book;
}

И следующий тест:

@RunWith(SpringRunner.class)
@DataJpaTest
public class BookRepositoryTest {

    @Autowired
    private TestEntityManager testEntityManager;

    @Autowired
    private BookRepository bookRepository;

    @Test
    public void delete() {
        // given
        String isbn = "isbn-1";
        Book book = new Book();
        book.setIsbn(isbn);
        testEntityManager.persist(book);


        Recommendation recommendation = new Recommendation();
        recommendation.setBook(book);
        testEntityManager.persist(recommendation);

        // when
        bookRepository.deleteBookByIsbn(book.getIsbn());

        // then
        assertThat(testEntityManager.find(Book.class, book.getId())).isNull();
        assertThat(testEntityManager.find(Recommendation.class, recommendation.getId())).isNull();
    }

}

@OnDelete(action = OnDeleteAction.CASCADE) отлично работает, когда этот код вызывается не из теста, а втест, я получаю исключение, что рекомендация не удаляется книгой.

Также я пытаюсь получить какую-либо информацию из sql, зарегистрированную для запросов гибернации, и я не вижу никаких операторов delete для этого теста.

Я не хочу использовать двунаправленное связывание для сущностей и просто пытаюсь понять, как решить эту конкретную проблему или как-то отладить ее.

Ответы [ 2 ]

2 голосов
/ 14 июня 2019

Несколько замечаний:

Во-первых, насколько мне известно, @OnDelete(action = OnDeleteAction.CASCADE) влияет только на генерацию DDL, т.е. FK создается в базе данных с предложением on delete cascade.Затем вы делегируете каскадное удаление в базу данных, и если у вас нет Hibernate, создающего схему, эта аннотация не будет иметь никакого эффекта.Поскольку каскадное удаление делегировано базе данных, вы не увидите никаких операторов SQL, выполняемых Hibernate.

Во-вторых, в своем тесте вы удаляете объект с помощью запроса JPQL:

bookRepository.deleteBookByIsbn(book.getIsbn());

, а не с использованием entityManager.remove(e) (с помощью метода delete(e) вашего хранилища).

Результатом этого является то, что даже если бы вы применили JPA CacadeType.DELETEдля ассоциации операция удаления не будет каскадной, поскольку массовые запросы на обновление / удаление JPQL не будут каскадными .

Подробнее об этом см. здесь:

JPA deleteвсе entites работает странно

1 голос
/ 13 июня 2019

@ ManyToOne # каскад

@ManyToOne(optional = false, cascade = CascadeType.ALL)
@JoinColumn(name = "book_id", nullable = false)
private Book book;

РЕДАКТИРОВАТЬ 1:

@ManyToOne(optional = false)
@JoinColumn(name = "book_id",
        nullable = false,
        foreignKey = @ForeignKey(
                foreignKeyDefinition = "FOREIGN KEY (book_id) REFERENCES book(id) ON DELETE CASCADE"
        )
)
private Book book;

Следующий подход должен помочь, если вам не нужны двунаправленные отображения и ваша схема создается из ваших энтитов.

Если вы создаете схему из SQL, вы также можете создать такой внешний ключ, но в своем скрипте.

Этот подход также предполагает выполнение только одного запроса на удаление.

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