Форум программистов, компьютерный форум, киберфорум
Java EE (J2EE)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/25: Рейтинг темы: голосов - 25, средняя оценка - 4.88
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517

Service, DAO, Entity, BO . Again

04.05.2013, 14:28. Показов 4721. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Ещё раз о том как разбить всё на эти сран... дурацкие уровни. Надеюсь в этот раз я хоть понял всех правильно. Взгляните пожалуйста и скажите всё ли так.

Итого моя мини архитектура для клиент-сервера (демонстрирую взаимодействие между уровнями на примере одной лишь сущности, но естественно что их много):
1)Entity которые есть в базе. Те такие объекты я могу получать из базы через jpa (хибернейт). Одна из них с названием подразделение:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Entity
@Table(name = "Department", schema = "dbo", catalog = "mydb")
@NamedQueries({
        здесь пачка @NamedQuery
                
})
public class Department implements java.io.Serializable {
    private static final long serialVersionUID = 1L;
    
     //ссылаются на названия named query
    public static final String findAll = "Department.findAll";
    public static final String findByID = "Department.findById";
    public static final String findByIDWithDetail = "Department.findByIdWithDetail";
    public static final String findAllWithDetail = "Department.findAllWithDetail";
    public static final String findByCriteria = "Department.findByCriteria";
    public static final String findByCriteriaWithDetail = "Department.findByCriteriaWithDetail";
 
    private Short dptId;
    private Department department;
    private String dptName;
    private String dptAdr;
    private Set<Department> departments = new HashSet<Department>(0);
    private Set<Employee> employees = new HashSet<Employee>(0);
 
    public Department() {
    }
 
    public Department(Short dptId, String dptName, String dptAdr) {
        this.dptId = dptId;
        this.dptName = dptName;
        this.dptAdr = dptAdr;
    }
    
    //остальные set / get
2)DAO уровень который получает entity из базы и отдаёт их уровню сервиса. DAO уровень у меня состоит из интерфейса для DAO
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface IDepartmentDAO {
    Department insert(Department info);
    Department update(Department info) throws SaveException;
    void delete (Department info) throws DeleteException;
 
    List<Department> find();
    List<Department> findWithDetail();
 
    Department find(Short id);
 
    List<Department> find(String criteria);
    List<Department> findWithDetail(String criteria);
 
}
}
и, собственно, самой реализации использующей hibernate:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Repository
@Transactional
public class DepartmentDAO implements IDepartmentDAO {
    @PersistenceContext
    private EntityManager em;
 
    @Override
    public Department insert(Department info) {
        em.persist(info);
        return info;
    }
 
    @Override
    public Department update(Department info){
        em.merge(info);
        return info;
    }
 
    @Override
    public void delete(Department info) {
        em.remove(info);
    }
 
    @Override
    @Transactional(readOnly=true)
    public List<Department> find() {
        List<Department> contacts = null;
        try{
            contacts = em.createNamedQuery(Department.findAll, Department.class).getResultList();
        } catch (NoResultException nr){
            contacts = new ArrayList<>(0);
        }
        return contacts;
    }
    //остальные реализации


3)BO объекты которые будут отправляться клиенту (кто-то ещё их называет View для пользователя) чтобы он ими мог пользоваться, из них грубо говоря "вырезано" то что клиенту знать не положено по устройству базы (на данной сущности правда это не очень наглядно так как здесь это почти та же entity):
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 *   Класс DepartmentBO для хранения информации о подразделении где работают сотрудники
 *   @version 1.00
 */
public class DepartmentBO {
    private static final long serialVersionUID = 100L;
 
    private Short dptId;
    private String dptName;
    private String dptAdr;
    private DepartmentBO mainDepartment;
 
    public DepartmentBO(Short dptId, String dptName, String dptAdr, DepartmentBO mainDepartment) {
        this.dptId = dptId;
        this.dptName = dptName;
        this.dptAdr = dptAdr;
        this.mainDepartment = mainDepartment;
    }
    
    //  set / get чего позволено пользователю
4)Сервис уровень, которым и будет пользоваться пользователь или юзать юзер (вот такая вот тавтология). Состоит из интерфейса:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface IDepartmentService {
    DepartmentBO insertDepartment(DepartmentBO info) throws SaveException;
    DepartmentBO updateDepartment (DepartmentBO info) throws SaveException;
    void removeDepartment (DepartmentBO info) throws DeleteException;
 
    DepartmentBO findDepartmentByID(Short id);
    DepartmentBO getParentDepartment(DepartmentBO department);
 
    List<DepartmentBO> findAllDepartments();
    List<DepartmentBO> findAllDepartmentsWithDetail();
 
    List<DepartmentBO> findDepartmentByCriteria(String criteria);
    List<DepartmentBO> findDepartmentByCriteriaWithDetail(String criteria);
}
и реализация интерфейса:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@Service("HTTPDepartmentService")
public class DepartmentService implements IDepartmentService {
    private Log log = LogFactory.getLog(DepartmentService.class);
 
    @Autowired
    IDepartmentDAO depDAO;//будет подсунута спрингом реализация на основе hibernate
 
    @Override
    public DepartmentBO insertDepartment(DepartmentBO info) throws SaveException{
        Department department = DepartmentConverter.convertFromBO(info);
 
        log.info("Insert new Department");
        try{
            depDAO.insert(department);
        } catch (CannotCreateTransactionException | IllegalStateException ex){
            log.error(ex);
            throw new SaveException("Can not respond your request now. Try later.");
        }
        log.info("Department saved with id: " + info.getDptId());
 
        info = DepartmentConverter.convertToBO(department);
        return info;
    }
 
    @Override
    public DepartmentBO updateDepartment(DepartmentBO info) throws SaveException {
        Department department = DepartmentConverter.convertFromBO(info);
 
        log.info("Update Department with id: " + info.getDptId());
        try{
            depDAO.update(department);
        } catch (CannotCreateTransactionException | IllegalStateException ex){
            log.error(ex);
            throw new SaveException("Can not respond your request now. Try later");
        }
 
        info = DepartmentConverter.convertToBO(department);
        return info;
    }
    // остальные реализации
5)Конвертеры. Так как сервис уровень оперирует объектами предназначенными для пользователя то возникает необходимость в их конвертировании в entity и назад для чего я дописал специальный класс-конвертер, выглядит весьма простенько:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class DepartmentConverter {
    /**
     * Конвертирует entity в BO
     * @param dep Entity объект для конвертации
     * @return Сконвертированный из Entity в BO объект
     */
    public static DepartmentBO convertToBO(Department dep){
        DepartmentBO result = null;
        if(dep != null){
            DepartmentBO mainDepartment = convertToBOWithoutLinks(dep.getDepartment());
            result = new DepartmentBO(dep.getDptId(),dep.getDptName(),dep.getDptAdr(), mainDepartment);
        }
        return result;
    }
 
    /**
     * Конвертирует Entity в BO без подтягивания связей по иерархии (заменяет ссылки на null)
     * @param department Объект для конвертирования
     * @return  Сконвертированный в BO объект без ссылок на другие (не POJO) объекты
     */
    public static DepartmentBO convertToBOWithoutLinks(Department department){
        DepartmentBO result = null;
        if(department != null)
            result = new DepartmentBO(department.getDptId(), department.getDptName(), department.getDptAdr(),null);
        return result;
    }
 
    /**
     * Конвертирует BO объект в Entity
     * @param depBO BO объект для конвертации
     * @return Entity объект сконвертированный из BO
     */
    public static Department convertFromBO(DepartmentBO depBO){
        if(depBO == null)
            throw new NullPointerException();
        Department result = new Department(depBO.getDptId(),depBO.getDptName(),depBO.getDptAdr());
        return result;
    }
И ... это всё, теперь моя архитектура корректная и похожа на каноническую тм или опять всё фигня и надо переделывать, но тогда подскажите что именно не так.

Добавлено через 5 минут
Кстати здесь же вопрос так как я не уверен что я поступил правильно когда в dao уровне просто выполняю операции типа merge/ remove/ persist, а на уровне сервиса отлавливаю исключения
Java
1
CannotCreateTransactionException | IllegalStateException ex
Это нормально или же dao уровень не должен выбрасывать специфические (jpa) исключения, а должен сам же их ловить и выбрасывать какой-то мой тип исключений уже чтобы сервис уровень не ловил jpa исключения, а ловил уже допустим тот же SaveException в знак того что нельзя обновить запись допустим. Или и так всё ок?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.05.2013, 14:28
Ответы с готовыми решениями:

DAO vs Service
Смотрю туториал и по ходу возникло пару вопросов. Есть dao интерфейс User public interface UserDao extends JpaRepository&lt;User,...

Интерфейс-Реализацаия в DAO и Service слое
Здравствуйте! Вопрос, наверное, детский, но просьба не бить по голове лопатой, просто все дело в....хм....проектировании,...

Spring слои Service, Controller, DAO. Бизнес-логика
Только начал изучать Spring и не до конца понимаю. Можете ли объяснить на примере приложения, который считывает строки из файла и инсертит...

4
 Аватар для mutagen
2587 / 2260 / 257
Регистрация: 14.09.2011
Сообщений: 5,185
Записей в блоге: 18
04.05.2013, 14:59
Цитата Сообщение от Gepar Посмотреть сообщение
теперь моя архитектура корректная и похожа на каноническую тм или опять всё фигня и надо переделывать, но тогда подскажите что именно не так.
блин - да загляни же в код примера что я дал по EE приложению наконец, сколько можно воду в ступе толочь?
канонических архитектур больше 1, один из вариантов (попроще) я привёл в ссылке, люди старались по шагам всё раскладывали, объясняли и на тебе - не подходит, подавай в разы сложнее когда ещё и в простом плаваем
0
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
04.05.2013, 19:00  [ТС]
mutagen, ок-ок, сейчас схожу по той ссылке ещё раз и ещё раз посмотрю на ту арихтектуру и на свою

Добавлено через 1 час 46 минут
Цитата Сообщение от mutagen Посмотреть сообщение
канонических архитектур больше 1
Так, кажеться я понял что тебя задело слово "каноническую", ок, тогда перефразирую последнее предложение первого поста в этой теме: эта архитектура нормальная? Нет ли в ней чего-то такого несуразного типа то что в dao не является этим самым dao, или то что делает сервис делать именно он не должен .
С теми примерами от нетбинса у меня сложности потому что я смотрю что там есть и вижу что это мне нафиг не надо так как у меня клиент на swing и он должен как-то редактировать данные, а не сохранять хитрые состояния корзинок

Добавлено через 1 час 7 минут
Так, я перечитал нетбиновские уроки (честно-честно, все-все) и всё равно не увидел у себя ошибок. То что там фасады (не знаю почему выбрано именно это слово) + сервлетные куски то у меня уровень сервиса, пока правда без сессонности, вроде всё ок же: сервис ходит в дао, получает объекты, конвертирует их и отдаёт клиенту; клиент редактирует свои бизнес объекты, отдаёт их сервису, тот их конвертирует в сущности и общается с дао через эти сущности. В случае если клиент налажал и сунул null или некорректные данные уровень сервиса даст клиенту исключение Save/Delete exception ... вроде всё как и положено, чего опять не так ?
0
 Аватар для mutagen
2587 / 2260 / 257
Регистрация: 14.09.2011
Сообщений: 5,185
Записей в блоге: 18
04.05.2013, 20:15
Цитата Сообщение от Gepar Посмотреть сообщение
чего опять не так ?
сервис это штука без логики, если у тебя контроллер реализующий логику в клиентском приложении, то у тебя смешанная архитектура. Нет авторизации. Фасады это такой шаблон проектирования, о нём и других читай отдельно.
Если я правильно понял твою текущую архитектуру, то это просто сетевой интерфейс для БД при помощи ORM.
Короче говоря отсутствует контроллер.
Сервис используется вообще непонятно почему, обычно их задача совместить различные ОС и платформы через единый WS интерфейс. Тут же таких необходимостей я не наблюдаю. Вполне можно было бы обойтись и банальным Remote интерфейсом EJB.
"Хитрые состояния корзинок" это бизнес логика, реализуй логику работы с клиентами и это будет контроллер "корзинок-клиентов".
Сервисы можно и оставить, но намотать на них секьюрити сложнее чем на EJB.
0
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
04.05.2013, 22:07  [ТС]
Цитата Сообщение от mutagen Посмотреть сообщение
Короче говоря отсутствует контроллер.
Ну я это тоже заметил Но контроллер у меня по сути является спринг, он предоставляет удалённый доступ клиента к этим сервисам.

Это ... я же клиента не показывал, всё вышеперечисленное у меня серверное (ну мои BO и exception'ы будут продублированы у клиента что само собой, конвертеры и т.д это всё будет у сервера).

Цитата Сообщение от mutagen Посмотреть сообщение
сервис это штука без логики, если у тебя контроллер реализующий логику в клиентском приложении, то у тебя смешанная архитектура.
а что же тогда должно конвертировать то что присылает пользователь в entity и обращаться к базе ? DAO же вроде должно работать только с базой и отдавать только entity, не его заботы все эти конвертации вроде, ну а кроме dao и сервисов в общем-то ничего и не осталось у меня ... или это должны были быть заботы контроллера конвертации данных туда-сюда? Повторюсь: у меня не веб приложение где я только показываю данные да товары в корзинки собираю, у меня двустороннее общение клиента и сервера в том плане что клиент присылает данные для добавления / обновления.

Цитата Сообщение от mutagen Посмотреть сообщение
Сервисы можно и оставить, но намотать на них секьюрити сложнее чем на EJB.
Ну я сейчас вообще не знаю как секьюрити "намотать". В инете написано что если используеться spring remote то можно использовать spring security для авторизации и типа как его прикрутить это любому дураку понятно и в описании не нуждается, но мне то не понятно Я сейчас без понятия как же этот spring security вкрутить чтобы клиент мог авторизироваться (разграничение ролей не надо, круто если будет, но вообще достаточно элементарного авторизовался / не авторизовался). Вы когда нибудь использовали spring security ? Может подскажите в какую сторону копать или же может есть какой-то вариант получше ?
Просто у меня изначально цель использовать спринг (ну как цель, это требование такое изначальное), а если я полезу в ejb то нафиг мне тогда спринг если всё умеет ejb ...

Добавлено через 8 минут
Сходил ещё раз в гугл чтобы найти клиент-сервер на spring с jpa не рассчитанный на веб мордашку и ... и его нет! Да что же это такое, это какая-то тайная технология или что, я найду себе пример где кто-то более опытный написал клиент-сервер как в реальном энетпрайз мир или нет, ну хоть один маленький примерчик
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
04.05.2013, 22:07
Помогаю со студенческими работами здесь

A Windows service with the name MySQL already exists. Please uninstall this service correctly or choose a different name for the new service.
Не знаю что делать дальше

@OneToOne or @ManyToOne on `my entity#1` references an unknown entity `my entity#2`
Привет всем! У меня появилась такая ошибка когда я работаю с двумя базами, именно когда делаю save в другую базу сущность первой, ...

Олицетворение (impersonating) системных учетных записей (NETWORK SERVICE, LOCAL SERVICE и пр.)
Возникла необходимость олицетворения потоком произвольной учетной записи, в т.ч. и системной. Пользуюсь LogonUser. С учетками, созданными...

The Lotus Domino Server Service Terminated With Service-specific Error
Может быть встречались с такой проблемой? The Lotus Domino Server Service Terminated With Service-specific Error 2351 At some point...

Сервер не заходит с никакой учётные запись кроме Administrator (The User Profile Service service failed)
Вчера мои сервер стала жертва вымогателей после этого сейчас сервер не заходит с никакой учётные запись кроме Administrator такие ошибки...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru