Запутался в шаблоне репозитория Spring-Data DDD - PullRequest
21 голосов
/ 12 мая 2011

Я не так много знаю о шаблоне хранилища DDD, но реализация в Spring сбивает меня с толку.

public interface PersonRepository extends JpaRepository<Person, Long> { … }

Поскольку интерфейс расширяет JpaRepository (или MongoDBRepository ...), если вы переходите с одногоБД на другой, вы должны также изменить интерфейс.

Для меня есть интерфейс, чтобы обеспечить некоторую абстракцию, но здесь это не так много абстрактно ...

Знаете ли вы, почемуSpring-Data работает так?

Ответы [ 3 ]

11 голосов
/ 12 мая 2011

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

И это именно то, что здесь происходит:

  • JpaRepository - это общее представление всех ваших репозиториев JPA (для всех различных сущностей), тогда как MongoDBRepository одинаково для всех сущностей MongoDB.
  • Но JpaRepository и MongoDBRepository не имеют ничего общего, кроме того, что определено в общих суперинтерфейсах:

    • org.springframework.data.repository.PagingAndSortingRepository
    • org.springframework.data.repository.Repository

Так что для меня это выглядит нормально.

Если вы используете классы, которые реализуют ваш репозиторий, то используйте PagingAndSortingRepository или Repository, если вы хотите иметь возможность переключаться с реализации JPA на реализацию на основе документов ( извините, но я не могу представить такой вариант использования - в любом случае ). И, конечно, ваша реализация репозитория должна реализовывать правильный интерфейс (JpaRepository, MongoDBRepository) в зависимости от того, что это такое.

7 голосов
/ 18 мая 2011

Причина этого довольно ясно изложена в этом сообщении в блоге http://blog.springsource.com/2011/02/10/getting-started-with-spring-data-jpa/.

Определение этого интерфейса служит двум целям: во-первых, расширяя JpaRepository, мы получаем набор общих методов CRUD в наш типэто позволяет сохранять учетные записи, удалять их и так далее.Во-вторых, это позволит инфраструктуре репозитория Spring Data JPA сканировать путь к классам для этого интерфейса и создать для него bean-компонент Spring.

Если вы не доверяете источникам, находящимся так близко к источнику (каламбур предназначен)было бы неплохо прочитать этот пост также http://www.brucephillips.name/blog/index.cfm/2011/3/25/Using-Spring-Data-JPA-To-Reduced-Data-Access-Coding.

То, что мне не нужно было кодировать, это реализация интерфейса PersonRepository.Spring создаст реализацию этого интерфейса и сделает bean-компонент PersonRepository доступным для автоматического подключения в мой класс Service.Компонент PersonRepository будет иметь все стандартные методы CRUD (которые будут транзакционными) и будет возвращать объекты Person или коллекцию объектов Person.Поэтому, используя Spring Data JPA, я сохранил написание своего собственного класса реализации.

3 голосов
/ 06 июля 2011

До версии M2 Spring Data мы требовали, чтобы пользователи продлили JpaRepository по следующим причинам:

  1. Инфраструктура сканирования пути к классам только подобрала интерфейсы, расширяющие этот интерфейс, поскольку можно было бы использовать Spring Data JPA и Spring Data Mongo параллельно, и оба они указывали бы на один и тот же пакет, неясно, для какого хранилища создать прокси-сервер. , Однако, начиная с RC1, мы просто оставляем это бремя для разработчика, так как считаем, что это довольно экзотический случай, и польза от использования Repository, CrudRepository или тому подобного перевешивает усилия, которые вы должны предпринять в только что описанном угловом случае. Вы можете использовать элементы exclude и include в пространстве имен, чтобы получить более полный контроль над этим.
  2. До M2 мы применяли транзакционность к методам CRUD, перераспределяя методы CRUD и помечая их @Transactional. Это решение, в свою очередь, было основано на алгоритме AnnotationTransactionAttributeSource, который используется для поиска конфигурации транзакции. Поскольку мы хотели предоставить пользователю возможность перенастроить транзакции, просто изменив метку метода CRUD в интерфейсе конкретного репозитория и применив к нему @Transactional. Для RC1 мы решили реализовать пользовательский TransactionAttributeSource, чтобы иметь возможность перемещать аннотации обратно в реализацию CRUD хранилища.

Короче говоря, вот что сводится к следующему:

Начиная с RC1 больше нет необходимости расширять интерфейс хранилища для конкретного хранилища, , за исключением , вы хотите ...

  1. Используйте List доступ к findAll(…) вместо Iterable в более основных интерфейсах репозитория (хотя вы можете просто переопределить соответствующие методы в общем базовом интерфейсе, чтобы получить List s как хорошо)
  2. Вы хотите использовать специфичные для JPA методы, такие как saveAndFlush(…) и т. Д.

Как правило, вы намного более гибки в отношении использования методов CRUD, начиная с RC1, поскольку вы можете даже расширить интерфейс маркера Repository и выборочно добавить методы CRUD, которые вы хотите выставить. Поскольку вспомогательная реализация будет по-прежнему реализовывать все методы PagingAndSortingRepository, мы все равно можем направить вызовы к экземпляру:

public interface MyBaseRepository<T, ID extends Serializable> extends Repository<T, ID> {

  List<T> findAll();

  T findOne(ID id);
}

public interface UserRepository extends MyBaseRepository<User, Long> {

  List<T> findByUsername(String username);
}

В этом примере мы определяем MyBaseRepository, чтобы выставлять только findAll() и findOne(…) (которые будут направлены в экземпляр, реализующий методы CRUD) и конкретный репозиторий, добавляя метод поиска к двум CRUD.

Для получения более подробной информации по этой теме, пожалуйста, обратитесь к справочной документации .

...