Если ваш сервисный уровень дублирует dao, вы вообще не используете сервисный уровень. Я допустил ту же ошибку в нескольких своих приложениях, и мне было интересно, «почему уровень обслуживания выглядит таким уродливым и дублирует DAO» ...
Сервисный уровень должен быть интерфейсом для вашего приложения, это означает, что некоторые методы не одинаковы в dao и в сервисе, но основная часть существенно отличается. Я не могу сказать это без просмотра остальной части вашего кода, но по вашему вопросу (который почти совпадает с моими вопросами несколько месяцев назад) мне кажется, что вы используете модель анемичного домена antipattern, В модели анемичной области ваша модель содержит только поля и методы получения, никаких реальных методов (поведения), что нарушает фундаментальные объектно-ориентированные принципы (объект == данные + поведение) ... ваше поведение, вероятно, похоже на сценарий транзакции в службе слой, но должен быть в вашей модели (слой домена).
Выходом из этого является использование модели расширенного домена (бины, вводимые для моделирования через @Configurable). Вы можете сказать, что это нарушает структуру слоев, и вы, вероятно, будете правы. Но я убежден, что мы должны думать о нашем приложении (домен + служба Dao +) как о едином компоненте (см. Alistair Cockburn Шестиугольная архитектура / Порты и адаптеры ).
Ваше приложение Swing / веб-клиент будет тогда клиентом для вашего основного компонента, затем вы сможете переключать их без каких-либо ограничений (потому что все, что содержит данные модификации в ядре).
Но у этого подхода есть ограничение / недостаток. Если вы будете использовать какую-то защиту (Spring security) или активные записи через спящий режим, то вам следует общаться со всеми клиентами через DTO (не с самими сущностями), потому что, когда вы связываетесь с сущностью, она может вызывать службу, которая будет активирована через транзакционный и может изменить базу данных (обойти вашу безопасность).
Я надеюсь, что я догадался о вашей архитектуре, если нет, то прошу прощения за изобретение колеса здесь, но этот пост может помочь кому-то, кто этого не знает (как я был несколько месяцев назад).
EDIT
на ваше редактирование: даже в простом приложении CRUD некоторые виды действий должны быть на уровне обслуживания - например, проверка (не проверка «это число», а некоторая проверка для конкретного бизнеса). Это не должно быть на ваш взгляд, потому что если вы измените его, вам придется скопировать и вставить его снова. Когда вы смотрите на свой код, вы должны спросить себя: «Если я решу написать тонкий клиент (просмотр в веб-браузере)», есть ли какой-нибудь код, который мне придется скопировать? Если ответ ДА, то вам следует создать сервисный метод для этого, возможно, удаленного вызова.
Другая вещь, которую вы должны / можете сделать на уровне сервиса, - это авторизация (разрешено ли пользователю в этой роли удалять эту запись). Чем вам понадобится сервисный слой почти для всех ваших сущностей, потому что простой пользователь должен иметь возможность редактировать (удалять) свои записи, но, вероятно, не должен удалять других пользователей. Но пользователь в роли администратора может сделать это.
Пример кода (часть статьи Сервисный интерфейс в моем приложении (Spring security)):
@Secured("ROLE_EDITOR")
public void save(ArticleDTO selectedArticle, ArticleDetailsDTO selectedArticleDetails);
В службе комментариев каждый может сохранить свои комментарии к статьям ....
И последнее замечание: вам, вероятно, следует подумать, если вам нужен уровень обслуживания вообще. Когда оно написано в хорошем виде, ваше приложение приобретет множество качеств в своей гибкости, возможности повторного использования и удобства обслуживания. Но написать это довольно сложно и отнимает много времени. Если вы не хотите делать все это (безопасность, модель расширенного домена, вызовы из большего количества интерфейсов (изменение реализации представления)), вы можете жить без этого: -)