Смутно о Spring -Data DDD файле репозитория
Я не так много знаю о шаблоне репозитория DDD, но реализация в Spring путают меня.
public interface PersonRepository extends JpaRepository<Person, Long> { … }
Поскольку интерфейс расширяет JpaRepository (или MongoDBRepository...), если вы переходите от одного db к другому, вам также нужно изменить интерфейс.
Для меня интерфейс есть, чтобы обеспечить некоторую абстракцию, но здесь она не так абстрактна...
Знаете ли вы, почему Spring -Дата работает так?
Ответы
Ответ 1
Вы правы, интерфейс - это абстракция о чем-то, что работает равным для всех реализующих классов, с внешней точки зрения.
И это именно то, что происходит здесь:
- JpaRepository - это общее представление обо всех ваших репозиториях JPA (для всех разных сущностей), в то время как MongoDBRepository одинаково для всех объектов MongoDB.
-
Но JpaRepository и MongoDBRepository не имеют ничего общего, кроме тех вещей, которые определены там, в общих супер интерфейсах:
- org.springframework.data.repository.PagingAndSortingRepository
- org.springframework.data.repository.Repository
Так что для меня это выглядит нормально.
Если вы используете классы, которые реализуют ваш репозиторий, используйте PagingAndSortingRepository или репозиторий, если вы хотите перейти от реализации JPA к реализации на основе документа (извините, но я не могу представить такой вариант использования - в любом случае). И, конечно, ваша реализация Репозитория должна реализовать правильный интерфейс (JpaRepository, MongoDBRepository) в зависимости от того, что это такое.
Ответ 2
Обоснование этого довольно четко указано в этом сообщении в блоге http://blog.springsource.com/2011/02/10/getting-started-with-spring-data-jpa/.
Определение этого интерфейса служит двум целям: во-первых, расширяя JpaRepository, мы получаем кучу общих методов CRUD в наш тип, который позволяет экономить учетные записи, удаляя их и т.д. Во-вторых, это позволит инфраструктуре репозитория Spring Data JPA сканировать путь к классам для этого интерфейса и создать для него Spring bean.
Если вы не доверяете источникам, близким к источнику (каламбур), неплохо было бы также прочитать этот пост http://www.brucephillips.name/blog/index.cfm/2011/3/25/Using-Spring-Data-JPA-To-Reduced-Data-Access-Coding. p >
То, что мне не нужно было кодировать, - это реализация интерфейса PersonRepository. Spring создаст реализацию этого интерфейса и сделает доступным PersonRepository bean для автоматического подключения к моему классу службы. PersonRepository bean будет иметь все стандартные CRUD-методы (которые будут транзакционными) и возвращать объекты Person или коллекцию объектов Person. Поэтому, используя Spring Data JPA, я сохранил свой собственный класс реализации.
Ответ 3
До M2 из Spring Data мы потребовали, чтобы пользователи расширили JpaRepository
по следующим причинам:
- Инфраструктура сканирования класса маршрутизировала только интерфейсы, расширяющие этот интерфейс, так как можно было бы использовать Spring Data JPA и Spring Data Mongo параллельно, и оба они указывали на тот же пакет, что было бы непонятно, создайте прокси-сервер. Однако с RC1 мы просто оставляем эту нагрузку разработчику, поскольку считаем это довольно экзотическим случаем и преимущество использования
Repository
, CrudRepository
или подобных перераспределений усилий, которые вы должны предпринять в только что описанном угловом случае. Вы можете использовать элементы exclude
и include
в пространстве имен, чтобы получить более тонкий контроль над этим.
- До M2 мы применяли транзакцию к методам CRUD, обновляя методы CRUD и аннотируя их с помощью
@Transactional
. Это решение, в свою очередь, было обусловлено алгоритмом AnnotationTransactionAttributeSource
, используемым для поиска конфигурации транзакции. Поскольку мы хотели предоставить пользователю возможность перенастроить транзакции, просто обновив CRUD-метод в конкретном интерфейсе репозитория и применив к нему @Transactional
. Для RC1 мы решили реализовать пользовательский TransactionAttributeSource
, чтобы иметь возможность переместить аннотации обратно в реализацию CRUD репозитория.
Короче говоря, вот что это сводится к:
По состоянию на RC1 нет необходимости расширять интерфейс хранилища конкретного хранилища, кроме, который вы хотите...
- Используйте
List
доступ к findAll(…)
вместо Iterable
на основе более основных интерфейсов репозитория (хотя вы могли бы просто повторно использовать соответствующие методы в общем базовом интерфейсе, чтобы возвращать List
)
- Вы хотите использовать специфичные для 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-тегам.
Подробнее об этой теме читайте в справочной документации .