Flex-Cairngorm / Hibernate — Стратегия быстрой выборки бессмысленна?

#apache-flex #hibernate #cairngorm #eager

#apache-flex #переход в спящий режим #cairngorm #нетерпеливый

Вопрос:

Я постараюсь быть как можно более кратким. Я использую технологии Flex / Hibernate для своего приложения. Я также использую микроархитектуру Cairngorm для Flex. Поскольку я новичок, я, вероятно, что-то неправильно понял в назначении Caringorm ModelLocator. У меня следующая проблема…

Предположим, что у нас есть следующая модель данных:

 USER  ---------------->  TOPIC  ------------->  COMMENT     
      1              M          1           M 
  

Пользователь может запускать много тем, в темах может быть много комментариев и т.д. Это довольно простая модель, просто для примера. В гибернации я использую стратегию быстрой выборки для однонаправленных связей ПОЛЬЗОВАТЕЛЬ-> ТЕМА и ТЕМА-> КОММЕНТАРИЙ (здесь нет вопроса о лучших практиках и т.д., это просто пример проблемы).

Мой ModelLocator выглядит следующим образом:

 ...
public class ModelLocator  ....
{
    //private instance, private constructor, getInstance() etc...
    ...

    //app state
    public var users:ArrayCollection;
    public var selectedUser:UserVO;
    public var selectedTopic:TopicVO;
}
  

Поскольку я использую быструю выборку, я могу «пройтись» по всему объектному графику на моем клиенте Flex, не обращаясь к базе данных. Это нормально, пока мне не нужно вставлять, обновлять или удалять некоторые экземпляры домена. Но когда это происходит, возникают проблемы с синхронизацией.

Например, если я хочу показать сведения о каком-то пользователе из некоторого UserListView, когда пользователь (актер) выберет этого пользователя в списке, я возьму выбранный индекс в списке пользователей, получу элемент из users ArrayCollection в ModelLocator по выбранному индексу и покажу сведения о выбранном пользователе.

Когда я захочу вставить нового пользователя, ок, я сохраню этого пользователя в базе данных и в методе IResponder result добавлю этого пользователя в ModelLocator.users ArrayCollection.

Но, когда я хочу добавить новую тему для какого-либо пользователя, если я все еще хочу использовать удобство быстрой выборки, мне нужно снова перезагрузить список пользователей… И добавить тему выбранному пользователю… И если пользователь находится в каком-то другом месте (косвенно), мне нужно вставить тему и туда. Обновление еще хуже. В этом случае мне нужно написать хотя бы какую-то логику…

Мой вопрос: это хороший способ использования ModelLocator в Cairngorm? Мне кажется, что из-за упомянутого, БЫСТРАЯ выборка каким-то образом бессмысленна. В случае использования БЫСТРОЙ выборки синхронизация на гибком клиенте может стать большой проблемой. Должен ли я всегда обращаться к базе данных, чтобы манипулировать моей моделью домена?

РЕДАКТИРОВАТЬ: Кажется, я недостаточно ясно выразился. Извините меня за это.

Хорошо, я также использую Spring в стеке технологий и шаблон DTO (DVO) с сериализатором flex / spring (de), но я просто хотел не вмешиваться в это, потому что я пытаюсь указать, как вы синхронизируетесь с состоянием базы данных в вашем приложении flex. Я даже не упоминаю многопользовательский сценарий и тему опроса / подталкивания, которая, возможно, является моим решением, потому что я использую стандартный механизм запроса-ответа. Я не предоставил какой-либо конкретный код, потому что для меня это кажется концептуальной проблемой, и я использую стандартные термины Cairngorm, чтобы объяснить псевдонимы, которые я использую для имен классов, имен переменных и т.д.

Я попытаюсь еще раз «упростить»: у вас есть гибкий клиент для администрирования вышеупомянутого домена (CRUD для каждого из классов домена), у вас есть ListOfUsersView (показывает список пользователей с базовой информацией о них), UserDetailsView (показывает данные пользователя и список пользовательских тем с возможностью удаления для каждой из тем), InsertNewUserTopicView (форма для вставки новой темы) и т.д.

Каждое представление, которое отображает некоторую информацию, синхронизировано с переменными состояния ModelLocator, например:

 ListOfUsersView ------binded to------> users:ArrayCollection in ModelLocator
UserDetailsView ------binded to------> selectedUser:UserVO in ModelLocator 
etc.
  

Переход состояния просмотра выглядит следующим образом:

 ListOfUsersView----detailsClick---->UserDetailsView---insertTopic--->InsertTopicView
  

Итак, когда я нажимаю на кнопку «Подробности» в ListOfUsersView, по моей логике, я получаю индекс выбранной строки в ListOfUsers, после этого я беру объект UserVO из users:ArrayCollection в ModelLocator по указанному индексу, после этого я устанавливаю этот объект UserVO как selectedUser: UserVO в ModelLocator и после этого я изменяю состояние просмотра на UserDetailsView( в нем отображаются сведения о пользователе и selectedUser.topics), который синхронизируется с selectedUser:UserVO в ModelLocator.

Теперь я нажимаю кнопку «Вставить новую тему» в UserDetailsView, что приводит к форме InsertTopicView. Я ввожу некоторые данные, нажимаю «Сохранить раздел»(после успешного сохранения снова отображается UserDetailsView) и возникает проблема.

Из-за моих нетерпеливо извлекаемых объектов, я не попал в базу данных при упомянутых переходах, и из-за этого есть два места, о которых мне нужно беспокоиться при вставке нового раздела для выбранного пользователя: один экземпляр объекта selectedUserв users:ArrayCollection (потому что моя логика выбирает пользователей из этой коллекции и показывает их в UserDetailsView), а второй — selectedUser: UserVO ( для того, чтобы синхронизировать UserDetailsView, который появляется после успешной операции сохранения).

Итак, снова возникает мой вопрос… Должен ли я обращаться к базе данных при каждом переходе, должен ли я перезагружать users: ArrayCollection и selectedUser: UserVO после сохранения, чтобы синхронизировать состояние базы данных с клиентом flex, должен ли я взять сохраненный раздел и на стороне клиента, не обращаясь к базе данных, программно передать все места, которые мне нужно обновить или …?

Мне кажется, что БЫСТРО извлекаемый объект с их ассоциациями — плохая идея. Я ошибаюсь?

Или, чтобы «упростить» 🙂 опять же, что вы должны делать в упомянутом сценарии? Итак, вам нужно обработать нажатие кнопки «Сохранить тему», и что теперь …?

Опять же, я действительно пытаюсь объяснить это как можно более пластично, потому что меня это смущает. Итак, пожалуйста, простите меня за мой длинный пост.

Ответ №1:

С моей точки зрения, дело не в самом режиме выборки, а во взаимодействии клиент-сервер. Из моего предыдущего опыта работы с этим я, наконец, обнаружил некоторые недостатки использования чистых объектов домена (особенно с быстрой выборкой) для взаимодействия клиент / сервер:

  • Вам нужно передать все дочерние коллекции, возможно, без необходимости использовать их на стороне клиента. В вашем случае очень вероятно, что вы будете отображать темы и комментарии не для всех пользователей, которых вы получаете с сервера. Наиболее похожая ситуация: вам нужно отобразить список пользователей, затем отобразить темы для одного из выбранных пользователей, а затем комментарии для одной из выбранных тем. Но в текущей реализации вы получаете все темы и комментарии, даже если они не нужны для отображения. Очень возможно, что вы получите всю свою базу данных за один запрос.
  • Еще одна проблема заключается в том, что может быть очень небезопасно получать все пользовательские данные (или некоторые другие данные) со всеми полями (электронные письма, адреса, пароли, номера кредитных карт и т.д.).

Я думаю, что могут быть другие причины не использовать объекты чистого домена, особенно при быстрой выборке.

Я предлагаю вам ввести некоторый уровень Mapper (или ассемблера) для преобразования объектов вашего домена в объекты передачи данных, известные как DTO. Таким образом, каждый запрос к вашему уровню обслуживания будет получать данные из вашего DAO или активной записи, а затем преобразовывать их в соответствующий DTO с помощью соответствующего Mapper. Таким образом, вы можете получить список пользователей без личных данных и запросить некоторые дополнительные сведения о пользователе с помощью отдельного запроса.

На стороне клиента вы можете использовать эти DTO напрямую или преобразовать их в объекты клиентского домена. Вы можете сделать это в своих ответчиках Cairngorm.

Таким образом, вы можете избежать многих проблем на стороне вашего клиента, которые вы описали.

Для слоя Mapper вы можете использовать библиотеку Dozer или создать свои собственные облегченные mappers.

Надеюсь, это поможет!

РЕДАКТИРОВАТЬ Что касается ваших данных, я бы предпочел получить список пользователей с необходимыми отображаемыми полями, такими как имя и фамилия (для отображения в списке). Назовите список SimpleUserRepresentationDTO .

Затем, если пользователь запрашивает данные пользователя для редактирования, вы запрашиваете UserDetailsDTO для этого пользователя и заполняете им поля tour selectedUser в модели. То же самое касается тем.

Единственная проблема заключается в отображении списка пользователей после редактирования сведений о пользователе. Вы можете:

  • Повторно запросите весь список. Преимущество в том, что вы можете отображать изменения, выполненные другими пользователями. Но если список слишком длинный, может быть очень неэффективно запрашивать всех пользователей каждый раз, даже если у них SimpleUserRepresentationDTO минимум данных.
  • Когда вы получаете успех от сервера при сохранении сведений о пользователе, вы можете найти соответствующего пользователя в списке пользователей модели и заменить измененные данные там.

Комментарии:

1. @Constantiner — Спасибо за ответ. Я отредактировал свой вопрос. Как я уже упоминал там, я использую шаблон DTO (или DVO), и я могу выбирать, какие данные я хочу сопоставить с объектами домена на стороне сервера с объектами на стороне клиента. Если я правильно понимаю, вы предлагаете мне упростить мои DTO и обращаться к базе данных за любой информацией, которая мне нужна (например, если мне нужны пользовательские темы, я буду запрашивать для них базу данных и так далее)?

2. Верно. Просто создайте простые и применимые DTO.

3. @slomir Я добавил некоторые детали к своему ответу.

4. @Constantiner — Большое вам спасибо (или Хвала ;). Я понял вашу точку зрения. Я улучшу степень детализации в DTO и применю ваш подход.

5. @Constantiner — Пожалуйста, извините за прерывание, у меня только один вопрос. Впервые в своем ответе вы предложили мне какой-то уровень ассемблера, точнее, Dozer. Это отличная библиотека, и теперь я понял ее назначение. Теперь на стороне сервера у меня есть свой уровень обслуживания, который возвращает объекты домена. Я не хочу это менять, потому что, возможно, в будущем мое приложение будет работать с классическим Spring MVC и т.д. Разумно ли создавать какой-либо уровень адаптера, чтобы адаптировать мой текущий интерфейс службы к вызовам клиента Flex? В adapter я вызову существующий уровень обслуживания, соберу свои DTO по своему усмотрению и верну их в flex.

Ответ №2:

Сказать по правде, хорошего способа использования Cairngorm не существует. Это дерьмовый фреймворк.

Я не совсем уверен, что именно вы подразумеваете под быстрой выборкой (или в чем именно заключается ваша проблема), но что бы это ни было, это все равно своего рода сделка типа запрос / ответ, и это не должно быть проблемой, скажем, если вы не делаете что-то неправильно; в этом случае я не вижу вашего кода.

Что касается фреймворков, я рекомендую вам взглянуть на RobotLegs или Parsley.

Комментарии:

1. Спасибо за ответ. Под СТРЕМЛЕНИЕМ я подразумеваю, что я получаю полный (или частичный) объектный граф при загрузке некоторых экземпляров (это зависит от сопоставления и конфигурации ассоциации hibernate). В моем примере я практически получаю всю базу данных, потому что, когда я получаю всех пользователей, каждый из них получает свои темы, каждая из тем — свои комментарии и т.д. Для упрощения моя проблема заключается в том, как синхронизировать это состояние приложения (график объектов) с состоянием базы данных после того, как я вставляю, обновляю, удаляю объекты домена в базе данных? Должен ли я зайти в базу данных и перезагрузить все снова или …?

2. Подождите, ваш клиент напрямую обращается к базе данных? Если это не проект Air, это очень большой запрет (и только если это локальная база данных). Между ними должен быть какой-то средний уровень (java, php, что-то еще). В любом случае, есть 2 способа получить ваши данные, путем опроса или нажатия. Опрос означает, что клиент запрашивает новые данные каждые x промежутков времени, в то время как push — это постоянное соединение с сервером, где сервер автоматически отправляет клиенту информацию о том, что изменилось, для чего клиент выполняет действие с указанными данными.

3. Нет. Я также использую Spring в качестве среднего слоя. Но вы упомянули 2 способа получения данных с сервера: опрос или нажатие (я думаю, что вы описываете длительный опрос). Я не учел это из-за загруженности сетевого трафика (в случае опроса или длительного опроса). Используете ли вы (длительный) опрос для синхронизации клиента с сервером? Сколько времени установить для опроса? Если это слишком долго, тогда возникает вопрос, как синхронизировать ваше состояние сразу после обновления состояния базы данных, с другой стороны, если оно слишком короткое, возникают проблемы с сетевым трафиком. Я открыт для этого решения, если вы можете дать мне несколько советов [Также смотрите Мою правку]

4. Нажатие точно не означает длительный опрос. Если вы используете ЖК-дисплеи, то используется протокол RTMP, который передает информацию в режиме реального времени. Однако длительный опрос хорошо работал для меня в прошлом, и это очень мало работы на переднем плане, это больше на внутренней стороне. Я уверен, что вы можете найти документацию в Интернете о времени опроса.

Ответ №3:

Посмотрите на проект «dpHibernate». Он реализует «отложенную загрузку» на клиенте Flex.