Автор оригинала: Anshul Bansal.
1. Обзор
Часто реализации репозитория и DAO считаются взаимозаменяемыми, особенно в приложениях, ориентированных на данные. Это создает путаницу в их различиях.
В этой статье мы обсудим различия между шаблонами DAO и репозиториями.
2. Шаблон ДАО
Шаблон объекта доступа к данным, он же DAO Pattern , является абстракцией сохранения данных и считается более близким к базовому хранилищу, которое часто ориентировано на таблицу .
Поэтому во многих случаях наши DAO соответствуют таблицам базы данных, позволяя более простой способ отправки/извлечения данных из хранилища, скрывая уродливые запросы.
Давайте рассмотрим простую реализацию шаблона DAO.
2.1. Пользователь
Во-первых, давайте создадим базовый класс User domain:
public class User { private Long id; private String userName; private String firstName; private String email; // getters and setters }
2.2. UserDao
Затем мы создадим интерфейс UserDao , который обеспечивает простые операции CRUD для домена User :
public interface UserDao { void create(User user); User read(Long id); void update(User user); void delete(String userName); }
2.3. UserDaoImpl
Наконец, мы создадим класс UserDaoImpl , который реализует интерфейс UserDao :
public class UserDaoImpl implements UserDao { private final EntityManager entityManager; @Override public void create(User user) { entityManager.persist(user); } @Override public User read(long id) { return entityManager.find(User.class, id); } // ... }
Здесь для простоты мы использовали интерфейс JPA EntityManager для взаимодействия с базовым хранилищем и предоставления механизма доступа к данным для домена User .
3. Шаблон репозитория
Согласно книге Эрика Эванса Domain-Driven Design , репозиторий ” – это механизм для инкапсуляции поведения хранения, поиска и поиска, который эмулирует коллекцию объектов.”
Аналогично, в соответствии с Шаблонами архитектуры корпоративных приложений , он “посредничает между доменом и уровнями отображения данных, используя интерфейс, подобный коллекции, для доступа к объектам домена.”
Другими словами, репозиторий также имеет дело с данными и скрывает запросы, аналогичные DAO. Однако он находится на более высоком уровне, ближе к бизнес-логике приложения.
Следовательно, репозиторий может использовать DAO для извлечения данных из базы данных и заполнения объекта домена. Или он может подготовить данные из объекта домена и отправить их в систему хранения, используя DAO для сохранения.
Давайте рассмотрим простую реализацию шаблона репозитория для домена User .
3.1. Информация о пользователе
Во-первых, давайте создадим интерфейс UserRepository :
public interface UserRepository { User get(Long id); void add(User user); void update(User user); void remove(User user); }
Здесь мы добавили несколько распространенных методов, таких как get , add , update и remove для работы с коллекцией объектов.
3.2. UserRepositoryImpl
Затем мы создадим класс UserRepositoryImpl , обеспечивающий реализацию интерфейса UserRepository :
public class UserRepositoryImpl implements UserRepository { private UserDaoImpl userDaoImpl; @Override public User get(Long id) { User user = userDaoImpl.read(id); return user; } @Override public void add(User user) { userDaoImpl.create(user); } // ... }
Здесь мы использовали UserDaoImpl для отправки/извлечения данных из базы данных.
До сих пор мы можем сказать, что реализации DAO и репозитория выглядят очень похожими, потому что класс User является анемичным доменом. Кроме того, репозиторий-это просто еще один слой поверх уровня доступа к данным (DAO).
Тем не менее, DAO кажется идеальным кандидатом для доступа к данным, а репозиторий-идеальным способом реализации бизнес-варианта использования .
4. Шаблон Репозитория С Несколькими DAO
Чтобы четко понять последнее утверждение, давайте расширим наш User домен для обработки бизнес-прецедента.
Представьте, что мы хотим подготовить профиль пользователя в социальных сетях, объединив его твиты в Twitter, сообщения в Facebook и многое другое.
4.1. Твит
Во-первых, мы создадим класс Tweet с несколькими свойствами, которые содержат информацию о твите:
public class Tweet { private String email; private String tweetText; private Date dateCreated; // getters and setters }
4.2. TweetDao и TweetDaoImpl
Затем, подобно UserDao , мы создадим интерфейс TweetDao , который позволяет извлекать твиты:
public interface TweetDao { ListfetchTweets(String email); }
Аналогично, мы создадим класс TweetDaoImpl , который обеспечивает реализацию метода fetchTweets :
public class TweetDaoImpl implements TweetDao { @Override public ListfetchTweets(String email) { List tweets = new ArrayList (); //call Twitter API and prepare Tweet object return tweets; } }
Здесь мы вызовем API Twitter, чтобы получить все твиты пользователя, используя его электронную почту.
Таким образом, в этом случае DAO предоставляет механизм доступа к данным с использованием сторонних API.
4.3. Расширение домена Пользователя
Наконец, давайте создадим подкласс User Social Media нашего класса User , чтобы сохранить список объектов Tweet :
public class UserSocialMedia extends User { private Listtweets; // getters and setters }
Здесь наш класс User Social Media представляет собой сложный домен, содержащий свойства домена User .
4.4. UserRepositoryImpl
Теперь мы обновим наш класс UserRepositoryImpl , чтобы предоставить объект User domain вместе со списком твитов:
public class UserRepositoryImpl implements UserRepository { private UserDaoImpl userDaoImpl; private TweetDaoImpl tweetDaoImpl; @Override public User get(Long id) { UserSocialMedia user = (UserSocialMedia) userDaoImpl.read(id); Listtweets = tweetDaoImpl.fetchTweets(user.getEmail()); user.setTweets(tweets); return user; } }
Здесь UserRepositoryImpl извлекает данные пользователя с помощью UserDaoImpl и твиты пользователя с помощью TweetDaoImpl.
Затем он объединяет оба набора информации и предоставляет объект домена класса User Social Media , который удобен для нашего бизнес-варианта использования. Поэтому репозиторий полагается на DAOS для доступа к данным из различных источников .
Аналогичным образом, мы можем расширить ваш Пользователь домен, чтобы сохранить список сообщений Facebook.
5. Сравнение двух моделей
Теперь, когда мы рассмотрели нюансы шаблонов DAO и репозитория, давайте обобщим их различия:
- DAO-это абстракция сохранения данных. Однако репозиторий-это абстракция коллекции объектов
- DAO-это концепция более низкого уровня, более близкая к системам хранения. Однако Репозиторий-это концепция более высокого уровня, более близкая к объектам домена
- DAO работает как уровень отображения данных/доступа, скрывая уродливые запросы. Однако репозиторий-это слой между доменами и уровнями доступа к данным, скрывающий сложность сортировки данных и подготовки объекта домена
- DAO не может быть реализован с помощью репозитория. Однако репозиторий может использовать DAO для доступа к базовому хранилищу
Кроме того, если у нас есть анемичный домен, репозиторий будет просто DAO.
Кроме того, шаблон репозитория поощряет доменный дизайн, обеспечивая легкое понимание структуры данных и для нетехнических членов команды|/.
6. Заключение
В этой статье мы исследовали различия между шаблонами DAO и репозиториями.
Во-первых, мы рассмотрели базовую реализацию шаблона DAO. Затем мы увидели аналогичную реализацию с использованием шаблона репозитория.
Наконец, мы рассмотрели репозиторий, использующий несколько DAO, расширяющий возможности домена для решения бизнес-задач.
Таким образом, мы можем сделать вывод, что шаблон репозитория доказывает лучший подход, когда приложение переходит от ориентированного на данные к бизнес-ориентированному.
Как обычно, все реализации кода доступны на GitHub .