2009-06-05 4 views
1

Итак, у меня есть простое веб-приложение с использованием Spring MVC + Hibernate, и я использую OpenSessionInViewFilter. Недавно я думал о замене пользовательского интерфейса чем-то вроде Flex или GWT.Когда ленивая загрузка становится проблемой в RIA?

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

Итак, допустим, что у меня есть способ вернуть Клиента, а у Клиента есть куча контактов, а у контактов есть куча Адресов и т. Д. Если я вызову getCustomer() из моего нового контроллера «RIA», он получит клиент, но коллекция контактов Клиента просто будет прокси или нулевым.

Я мог бы создать новый слой поверх того, что у меня уже есть, что возвращает DTO, которые предварительно заполнены ... но ... похоже, что это будет сложно.

Любые советы?

ответ

2

Вы абсолютно правы, что это создает проблему для RIA. Если вы используете OpenSessionInViewFilter, тогда данные не будут возвращены null; скорее, сериализатор будет перемещаться по всему графику объекта и отправлять огромное количество данных назад. Это вызовет серьезные проблемы с производительностью.

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

Другим подходом является введение слоя непосредственно перед сериализатором, который подготавливает граф объекта для сериализации. Один из подходов, который мы использовали в некоторых предыдущих проектах, заключался в том, чтобы представить аспект уровня обслуживания, который будет перемещать весь граф объекта и заменять ленивых прокси новым экземпляром Entity с его набором свойств @Id. Если график будет восстановлен позже, это обеспечит, чтобы отношения @ManyToOne не были случайно отвергнуты. Вы можете вызвать getters или использовать Hibernate.initialize(), чтобы принудительно инициализировать данные, которые вы хотите отправить по кабелю. Это усложняется, когда вы вводите каскадное сохранение связей @OneToMany или @ManyToMany в Hibernate.

Недавно я наткнулся на solutin под названием Gilead, который предназначен для решения этой проблемы. Он использует подход, аналогичный описанному выше:

http://noon.gilead.free.fr/gilead/

Я также считаю, Гранит DS имеет решение этой проблемы в рамках своей структуры Tide:

http://www.graniteds.org/confluence/display/DOC/4.+Lazy+Initialization

Одна проблема, которую я не думайте, что кто-то решил - это способ фактически ленить данные загрузки в RIA с сервера.Я думаю, что это, безусловно, можно было бы сделать, но здесь есть некоторые проблемы с безопасностью. Вам понадобится довольно надежная проверка безопасности, чтобы убедиться, что любые попытки ленивой загрузки данных были у пользователя, который на самом деле имеет разрешение на загрузку этих данных в первую очередь.

+0

Спасибо! Есть ли у вас опыт работы с dpHibernate? Я думаю, что это может решить эту проблему для меня, но я не уверен (то есть, если я решила использовать Flex). – Boden

+0

Я не кодировал dpHibernate, хотя я просмотрел документацию. Одна из серьезных проблем, которые я испытывал, заключалась в том, что, похоже, это не затрагивало вопросы безопасности, но я, возможно, что-то пропустил. –

+0

Можете ли вы подробно рассказать о проблемах безопасности, которые у вас есть? – Boden

0

Если для вашего уровня презентации требуется наличие контактов с клиентом, это обеспечит слой данных. Цель lazy loading - не пропустить данные ... она используется в компьютерном программировании для отсрочки инициализации объекта до тех пор, пока он не понадобится.

Вам не нужно беспокоиться.

+0

Хм, это не имеет для меня никакого смысла. Объекты, которые я возвращаю, будут сериализованы, поэтому все, что они содержат, должно быть загружено до их отправки. Поэтому, если я вызываю метод getCustomer(), и у Клиента есть коллекция, скажем, «Контакты», которая загружается с леними, объект Customer не будет содержать действительный набор контактов во время сериализации. Когда клиент пытается получить getCustomer(). GetContacts(), он ничего не получит. – Boden

+0

На самом деле, похоже, мои проблемы могут быть реализованы в обратном порядке - все будет загружаться при сериализации (по крайней мере, с использованием пружинных пружин) ..., что представляет собой общую проблему. См. Следующее: http://www.infoaccelerator.net/blog/post.cfm/bypassing-hibernate-s-lazy-loading-in-blazeds-with-spring – Boden