Рубрики
Без рубрики

Весенние данные JPA Удалить и отношения

Изучите различные способы удаления сущностей в JPA весенних данных.

Автор оригинала: baeldung.

1. Обзор

В этом учебнике мы посмотрим, как удаление делается в Весенние данные JPA .

2. Образец сущности

Как мы знаем из справочная документация Spring Data JPA интерфейсы репозиториев предоставляют нам некоторую базовую поддержку сущностей.

Если у нас есть сущность, как Книжный :

@Entity
public class Book {

    @Id
    @GeneratedValue
    private Long id;
    private String title;

    // standard constructors

    // standard getters and setters
}

Затем мы можем расширить срок службы весенних данных CrudRepository предоставить нам доступ к операциям CRUD в Книжный :

@Repository
public interface BookRepository extends CrudRepository {}

3. Удаление из репозитория

Среди прочего, CrudRepository содержит два метода: удалитьБиид и удалитьВсе .

Давайте проверить эти методы непосредственно из нашей BookRepository :

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class})
public class DeleteFromRepositoryUnitTest {

    @Autowired
    private BookRepository repository;

    Book book1;
    Book book2;
    List books;

    // data initialization

    @Test
    public void whenDeleteByIdFromRepository_thenDeletingShouldBeSuccessful() {
        repository.deleteById(book1.getId());
        assertThat(repository.count()).isEqualTo(1);
    }

    @Test
    public void whenDeleteAllFromRepository_thenRepositoryShouldBeEmpty() {
        repository.deleteAll();
        assertThat(repository.count()).isEqualTo(0);
    }
}

И даже несмотря на то, что мы используем CrudRepository , обратите внимание, что эти же методы существуют для других интерфейсов Spring Data JPA, таких как JpaRepository или PagingAndSortingRepository.

4. Полученный запрос удаления

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

Полученный запрос удаления должен начинаться с удалить , а затем название критериев отбора. Эти критерии должны быть предусмотрены в вызове метода.

Допустим, мы хотим удалить Книжный s по титульный . Используя конвенцию о наименовании, мы начнем с удалить и список титульный в качестве наших критериев:

@Repository
public interface BookRepository extends CrudRepository {
    long deleteByTitle(String title);
}

Значение возврата, типа долго , указывает, сколько записей метод удален.

Давайте напишем тест и убедитесь, что это правильно:

@Test
@Transactional
public void whenDeleteFromDerivedQuery_thenDeletingShouldBeSuccessful() {
    long deletedRecords = repository.deleteByTitle("The Hobbit");
    assertThat(deletedRecords).isEqualTo(1);
}

Упорство и удаление объектов в JPA требует транзакции, поэтому мы должны использовать @Transactional аннотация при использовании этих производные запросы на удаление , чтобы убедиться, что транзакция запущена. Об этом подробно говорится в ORM с весенней документацией .

5. Пользовательский запрос удаления

Названия методов для производных запросов могут получить довольно долго, и они ограничены только одной таблицей.

Когда нам нужно что-то более сложное, мы можем написать пользовательский запрос, используя @Query и @Modifying вместе.

Давайте проверим эквивалентный код для нашего производного метода из более ранних:

@Modifying
@Query("delete from Book b where b.title=:title")
void deleteBooks(@Param("title") String title);

Опять же, мы можем проверить, он работает с простым тестом:

@Test
@Transactional
public void whenDeleteFromCustomQuery_thenDeletingShouldBeSuccessful() {
    repository.deleteBooks("The Hobbit");
    assertThat(repository.count()).isEqualTo(1);
}

Оба представленных выше решения схожи и достигают одного и того же результата. Тем не менее, они принимают несколько иной подход.

тем @Query метод создает единый запрос JP’L против базы данных. Для сравнения, deleteBy методы выполняют запрос чтения, а затем удаляют каждый из элементов по одному.

6. Удалить в отношениях

Давайте посмотрим, что произойдет, когда мы отношения с другими сущностями.

Предположим, у нас есть Категория лица, которое имеет OneToMany ассоциации с Книжный сущность:

@Entity
public class Category {

    @Id
    @GeneratedValue
    private Long id;
    private String name;

    @OneToMany(mappedBy = "category", cascade = CascadeType.ALL, orphanRemoval = true)
    private List books;

    // standard constructors

    // standard getters and setters
}

КатегорияРепозиторий может быть просто пустой интерфейс, который расширяет CrudRepository :

@Repository
public interface CategoryRepository extends CrudRepository {}

Мы также должны изменить Книжный сущности, отражающей эту ассоциацию:

@ManyToOne
private Category category;

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

@Test
public void whenDeletingCategories_thenBooksShouldAlsoBeDeleted() {
    categoryRepository.deleteAll();
    assertThat(bookRepository.count()).isEqualTo(0);
    assertThat(categoryRepository.count()).isEqualTo(0);
}

Это не двунаправлению, однако. Это означает, что если мы удалим книги, категории по-прежнему существует:

@Test
public void whenDeletingBooks_thenCategoriesShouldAlsoBeDeleted() {
    bookRepository.deleteAll();
    assertThat(bookRepository.count()).isEqualTo(0);
    assertThat(categoryRepository.count()).isEqualTo(2);
}

Мы можем изменить это поведение, изменив свойства отношений, такие как CascadeType.

7. Заключение

В этой статье мы рассмотрели различные способы удаления сущностей в Spring Data JPA. Мы рассмотрели предоставленные методы удаления из CrudRepository , а также наши производные запросы или пользовательские запросы с использованием @Query аннотация.

Мы также имели взгляд на как удаление сделано в отношениях. Как всегда, все фрагменты кода, упомянутые в этой статье, можно найти на наш репозиторий GitHub .