сразу скажу не использую ORM
Сразу скажу - используйте ORM.
class UserService{
И где тут DDD? Где единый язык?
Вопрос такой, где производить сборку готовой сущности для дальнейшего использования,
В репозитории или в одной из его зависимостей. В частности в Doctrine2 репозиторий запрашивает сущность в entity manager-а, который загружает их сначала в unit of work, который хранит все в identity map для того что бы не допускать дублей сущностей (если мы будем каким либо образом запрашивать одну и ту же сущность, ORM вернет вам один и тот же объект, что делает использование ORM собственно и удобным). Внутренний мэппер мэпит данные из базы на сущности с использованием гидраторов.
При сохранении происходит flush Unit-of-Work, при котором вычисляются изменения во всех сущностях и генерится SQL.
то есть вам в любом случае нужно реализовать мэппер объектов либо взять готовый, затем вам нужно реализовать Unit-of-work, затем лоадер данных из базы ну и т.д. Я обдумывал вариант легкой замены Doctrine2 и понял что это в принципе практически не возможно. Именно по этой причине существует не так много реализаций data-mapper, для PHP это только доктрина, для Java это Hibernate, для Python - SQLAlchemy... и как бы больше реализаций и нет.
Дядя Боб в одном из своих докладов на тему архитектуры приложенй (запамятовал название, поищу) рассказывал на эту тему много чего, мол и про загоны "не использовать ORM" которые были в 90-х, и почему реализация дата мэппера это весьма сложная задача....
p.s. вывод - берите Doctrine2 ORM и не засоряйте себе голову попытками реализовать дата мэппер самостоятельно - это очень сложная задача. Именно поэтому не так много реализаций этого подхода.