Образцовый шаблон - как его понять и как он работает с "сложными" объектами?
Мне сложно понять шаблон репозитория.
Есть много мнений по этой теме, например, в Образцовый шаблон, сделанный правильно, а также другие вещи, такие как Репозиторий - это новый синглтон или снова, как в Не используйте репозиторий использования DAO или просто возьмите Spring JPA Data + Hibernate + MySQL + MAVEN, где каким-то образом репозиторий выглядит таким же, как объект DAO.
Я устал читать это, так как imho это не может быть такой трудной, как это показано во многих статьях.
Я вижу это так: кажется, что я хочу что-то вроде этого:
------------------------------------------------------------------------
| Server |
------------------------------------------------------------------------
| | | |
Client <-|-> Service Layer <-|-> Repository Layer <-|-> ORM / Database Layer |
| | | |
------------------------------------------------------------------------
Service Layer
принимает объекты *DTO
и передает их в Repository Layer
, который в основном представляет собой не что иное, как "парень", который знает, как можно сохранить объект.
Например, предположим, что у вас есть состав некоторых инструментов (обратите внимание, что это всего лишь псевдокод)
@Entity
class ToolSet {
@Id
public Long id;
@OneToOne
public Tool tool1;
@OneToOne
public Tool tool2;
}
@Entity
class Tool {
@Id
public Long id;
@OneToMany
public ToolDescription toolDescription;
}
@Entity
class ToolDescription {
@Id
public Long id;
@NotNull
@OneToOne
public Language language
public String name;
public String details;
}
То, что я не получаю, является той частью, где я получаю объект ToolSetDTO
от клиента.
Как я понял, до сих пор я мог написать ToolSetRepository
с помощью метода ToolSetRepository.save(ToolSetDTO toolSetDto)
, который "знает, как хранить" a ToolSetDTO
. Но почти каждый учебник не передает *DTO
, а Entity
.
Меня беспокоит то, что если вы возьмете мой пример ToolSet
сверху, мне нужно будет сделать следующие шаги:
- Возьмите
ToolSetDTO
и проверьте, не стоит ли null
- Для каждого
tool*Dto
, принадлежащего ToolSetDTO
a) Если имеет действительный идентификатор, то конвертируйте из DTO
в Entity
в противном случае создайте новую запись в базе данных
b) toolDescriptionDto
и конвертировать/сохранить его в базу данных или создать новую запись
- После проверки этих выше instanciate
ToolSet
(entity) и настройте его для сохранения в базе данных
Все это слишком сложно, чтобы просто разрешить эту функцию службы (интерфейс для клиента).
То, что я думал о создании, например, a ToolSetRepository
, но вопрос здесь
- Требуется ли объект объекта
ToolSet
или он использует объект DTO
?
- В любом случае: разрешено ли
*Repository
использовать другие объекты репозитория? Например, когда я хочу сохранить ToolSet
, но сначала мне нужно сохранить Tool
и ToolDescription
- использовать ToolRepository
и ToolDescriptionRepository
внутри ToolSetRepository
?
Если да: почему он не разбивает шаблон хранилища? Если этот шаблон является в основном слоем между сервисом и моей инфраструктурой ORM, он просто не" чувствует себя хорошо", чтобы добавлять зависимости к другим классам *Repository
из-за причин зависимости.
Я не знаю, почему я не могу об этом подумать. Это звучит не так сложно, но там все еще помогает, например, Spring Data
. Другое дело, что беспокоит меня, так как я действительно не понимаю, как это облегчает ситуацию. Тем более, что я уже использую Hibernate - я не вижу преимущества (но, возможно, это другой вопрос).
Итак, я знаю, что это длинный вопрос, но я уже провел несколько дней исследований. Там уже существующий код, над которым я сейчас работаю, начинает становиться беспорядком, потому что я просто не вижу этого шаблона.
Я надеюсь, что кто-то может дать мне большую картину, чем большинство статей и руководств, которые не выходят за рамки реализации очень простого примера шаблона репозитория.
Ответы
Ответ 1
Вы можете прочитать мой "репозиторий для манекенов" post, чтобы понять простой принцип репозитория. Я думаю, ваша проблема в том, что вы работаете с DTO, и в этом сценарии вы действительно не используете шаблон репозитория, вы используете DAO.
Основное различие между репозиторией и дао заключается в том, что репозиторий возвращает только объекты , которые понимаются вызывающим уровнем. В большинстве случаев репозиторий используется бизнес-слоем и, таким образом, он возвращает бизнес-объекты. Дао возвращает данные, которые могут быть или не быть целым бизнес-объектом, т.е. Данные не являются допустимой бизнес-концепцией.
Если ваши бизнес-объекты - это просто структуры данных, это может быть подсказкой, что у вас есть проблема моделирования, например, плохой дизайн. Репозиторий имеет больше смысла с "богатыми" или, по крайней мере, правильно инкапсулированными объектами. Если вы просто загружаете/сохраняете структуры данных, вероятно, вам не нужен репозиторий, достаточно orm.
Если вы имеете дело с бизнес-объектами, которые состоят из других объектов (агрегата), и этот объект нуждается во всех его частях, чтобы быть согласованным (совокупным корнем), то шаблон репозитория лучшее решение, потому что оно будет абстрагировать все детали сохранения. Ваше приложение просто попросит "Продукт", и репозиторий вернет его в целом, независимо от того, сколько таблиц или запросов требуется для восстановления объекта.
На основе вашего примера кода у вас нет "реальных" бизнес-объектов. У вас есть структуры данных, используемые Hibernate. Бизнес-объект разработан на основе бизнес-концепций и вариантов использования. Репозиторий позволяет BL не заботиться о том, как этот объект сохраняется. В некотором смысле репозиторий действует как "конвертер/картограф" между объектом и моделью, которые будут сохраняться. В основном репо "уменьшает" объекты до требуемых для данных сохранения.
Бизнес-объект не является сущностью ORM. Это может быть с технической точки зрения, но из проекта pov один из них - бизнес-модель других моделей. Во многих случаях они несовместимы напрямую.
Самая большая ошибка заключается в разработке вашего бизнес-объекта в соответствии с потребностями хранения и мышлением. И вопреки тому, что многие разработчики считают, целью ORM является не сохранение бизнес-объектов. Его цель - имитировать базу данных "oop" поверх rdbms. Отображение ORM находится между вашими объектами и таблицами db, а не между объектами приложения (даже при работе с бизнес-объектами) и таблицами.