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

Создание репозитория только для чтения с данными Spring

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

1. Обзор

В этом коротком уроке мы обсудим, как создать репозиторий только для чтения Spring Data |.

Иногда необходимо считывать данные из базы данных без необходимости их изменения. В этом случае было бы идеально иметь интерфейс Repository только для чтения.

Он обеспечит возможность считывания данных без риска их изменения кем-либо.

2. Расширение репозитория

Давайте начнем с проекта Spring Boot, который включает в себя spring-boot-starter-data-jpa зависимость :


    org.springframework.boot
    spring-boot-starter-data-jpa
    2.4.3

В эту зависимость включен популярный интерфейс Spring Data CrudRepository , который поставляется с методами для всех основных операций CRUD (создание, чтение, обновление, удаление), необходимых большинству приложений. Однако он включает в себя несколько методов, которые изменяют данные, и нам нужен репозиторий, который имеет возможность только считывать данные.

CrudRepository фактически расширяет другой интерфейс, называемый Репозиторием . Мы также можем расширить этот интерфейс в соответствии с нашими потребностями.

Давайте создадим новый интерфейс, который расширяет Репозиторий :

@NoRepositoryBean
public interface ReadOnlyRepository extends Repository {
    Optional findById(ID id);
    List findAll();
}

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

Также важно отметить, что мы должны использовать аннотацию @NoRepositoryBean , чтобы сообщить Spring, что мы хотим, чтобы этот репозиторий оставался универсальным. Это позволяет нам повторно использовать наш репозиторий только для чтения для стольких различных сущностей, сколько мы захотим.

Далее мы рассмотрим, как привязать объект к нашему новому репозиторию Только для чтения .

3. Расширение репозитория только для чтения

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

@Entity
public class Book {
    @Id
    @GeneratedValue
    private Long id;
    private String author;
    private String title;

    //getters and setters
}

Теперь, когда у нас есть устойчивая сущность, мы можем создать интерфейс репозитория, который наследуется от нашего ReadOnlyRepository :

public interface BookReadOnlyRepository extends ReadOnlyRepository {
    List findByAuthor(String author);
    List findByTitle(String title);
}

В дополнение к двум методам, которые он наследует, мы добавили еще два метода, предназначенных только для чтения книг: findByAuthor() и findByTitle() . В общей сложности этот репозиторий имеет доступ к четырем методам только для чтения.

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

@Test
public void givenBooks_whenUsingReadOnlyRepository_thenGetThem() {
    Book aChristmasCarolCharlesDickens = new Book();
    aChristmasCarolCharlesDickens.setTitle("A Christmas Carol");
    aChristmasCarolCharlesDickens.setAuthor("Charles Dickens");
    bookRepository.save(aChristmasCarolCharlesDickens);

    Book greatExpectationsCharlesDickens = new Book();
    greatExpectationsCharlesDickens.setTitle("Great Expectations");
    greatExpectationsCharlesDickens.setAuthor("Charles Dickens");
    bookRepository.save(greatExpectationsCharlesDickens);

    Book greatExpectationsKathyAcker = new Book();
    greatExpectationsKathyAcker.setTitle("Great Expectations");
    greatExpectationsKathyAcker.setAuthor("Kathy Acker");
    bookRepository.save(greatExpectationsKathyAcker);

    List charlesDickensBooks = bookReadOnlyRepository.findByAuthor("Charles Dickens");
    Assertions.assertEquals(2, charlesDickensBooks.size());

    List greatExpectationsBooks = bookReadOnlyRepository.findByTitle("Great Expectations");
    Assertions.assertEquals(2, greatExpectationsBooks.size());

    List allBooks = bookReadOnlyRepository.findAll();
    Assertions.assertEquals(3, allBooks.size());
    
    Long bookId = allBooks.get(0).getId();
    Book book = bookReadOnlyRepository.findById(bookId).orElseThrow(NoSuchElementException::new);
    Assertions.assertNotNull(book);
}

Чтобы сохранить книги в базе данных, прежде чем читать их обратно, мы создали Хранилище книг , которое расширяет CrudRepository в области тестирования. Этот репозиторий не нужен в основной области проекта, но был необходим для этого теста.

public interface BookRepository
  extends BookReadOnlyRepository, CrudRepository {}

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

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

Мы узнали, как расширить интерфейс Репозитория Spring Data, чтобы создать многоразовый репозиторий только для чтения. После этого мы привязали его к простой сущности Book и написали тест, который доказал, что его функциональность работает так, как мы ожидали.

Как всегда, рабочий пример этого кода можно найти на GitHub .