Открыть сессию в виде шаблона - PullRequest
13 голосов
/ 04 декабря 2009

Я задаю этот вопрос с учетом выбранных мной сред разработки JPA (реализация Hibernate), Spring и .

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

На мой взгляд, у меня есть следующие альтернативы при извлечении сущностей и их ассоциаций:

  1. Используйте шаблон Open Session In View, чтобы создать сеанс для каждого запроса и зафиксировать транзакцию перед возвратом ответа.

  2. Реализуйте слой DTO (Data Transfer Object) так, чтобы каждый выполняемый мной запрос DAO возвращал правильно инициализированный DTO для моих целей. Мне не очень нравится эта опция, потому что по своему опыту я обнаружил, что она создает много шаблонного кода для копирования и становится грязной в обслуживании.

  3. Не отображайте никакие ассоциации в JPA, чтобы каждый выполняемый мной запрос возвращал только интересующие меня сущности - это, вероятно, потребует от меня наличия DTO в любом случае, и будет трудно поддерживать, и я думаю, что поражения цель наличия ORM на первом месте.

  4. С нетерпением извлекайте все (или большинство ассоциаций) - в приведенном выше примере всегда извлекайте все строки заказа, когда я получаю заказ.

Итак, мой вопрос: когда и при каких обстоятельствах вы бы использовали какой из этих вариантов? Вы всегда придерживаетесь одного способа сделать это?

Я бы попросил коллегу, но думаю, что если бы я даже упомянул термин «Открытая сессия в поле зрения», меня бы встретили пустыми взглядами :( Что я действительно ищу, так это несколько советов от старшего или очень опытного разработчик.

Спасибо, ребята!

Ответы [ 6 ]

15 голосов
/ 04 декабря 2009

У открытого сеанса в представлении есть некоторые проблемы .

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

Другой пример, чтение данных по требованию может обернуться многими «N + 1 select» проблемами , которые снижают вашу производительность.


Многие проекты используют следующий путь:

  1. Ведение транзакций на бизнес-уровне ; загрузите в этот момент все, что вам нужно.
  2. Уровень представления подвержен риску LazyExceptions: каждый считается ошибкой программирования, обнаруживается во время тестов и исправляется путем загрузки большего количества данных на бизнес-уровне (у вас есть возможность сделать это эффективно, избегая " N + 1 выберите «проблемы».

Чтобы избежать создания дополнительных классов для DTO, вы можете загрузить данные внутри самих объектов сущности . В этом весь смысл подхода POJO (используется современными уровнями доступа к данным и даже технологиями интеграции, такими как Spring).

10 голосов
/ 04 декабря 2009

Я успешно решил все свои проблемы с отложенной инициализацией с помощью Open Session In View -pattern (т. Е. Реализация Spring). Технологии, которые я использовал, были такими же, как у вас.

Использование этого шаблона позволяет мне полностью отобразить отношения сущностей и не беспокоиться о получении дочерних сущностей в дао. В основном. В 90% случаев шаблон решает ленивые потребности инициализации в представлении. В некоторых случаях вам придется «вручную» инициализировать отношения. Эти случаи были редкими и всегда включали очень очень сложные отображения в моем случае.

При использовании Open Entity Manager в шаблоне View важно правильно определить отношения между сущностями и особенно параметры распространения и транзакции. Если они не настроены должным образом, будут возникать ошибки, связанные с закрытыми сеансами, когда какой-либо объект лениво инициализируется в представлении и происходит сбой из-за того, что сеанс уже закрыт.

Я бы определенно пошел с вариантом 1. Иногда может потребоваться вариант 2, но я не вижу абсолютно никакой причины использовать вариант 3. Вариант 4 также является «нет». Стремительная загрузка всего убивает производительность любого представления, которому нужно перечислить лишь несколько свойств некоторых родительских объектов (в данном случае это порядки).

N + 1 выбирает

Во время разработки будет N + 1 выбор в результате инициализации некоторых отношений в представлении. Но это не повод отказаться от паттерна. Просто исправьте эти проблемы по мере их возникновения и перед доставкой кода в производство. Устранить эти проблемы с помощью шаблона OEMIV так же легко, как и с любым другим шаблоном: добавить надлежащие методы dao или service, настроить контроллер на вызов другого метода поиска, возможно, добавить представление в базу данных и т. Д.

3 голосов
/ 03 июля 2010

Я успешно использовал шаблон Open-Session-in-View в проекте. Однако недавно я прочитал в «Spring In Practice» интересную потенциальную проблему с неповторяющимися операциями чтения, если вы управляете своими транзакциями на более низком уровне, сохраняя сеанс Hibernate открытым на уровне представления.

Мы управляли большинством наших транзакций на уровне сервисов, но оставляли сеанс гибернации открытым на уровне просмотра. Это означало, что отложенное чтение в представлении приводило к отдельным транзакциям чтения.

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

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

1 голос
/ 19 января 2010

Я также сброслю свой вес за паттерн Open-Session-in-View, будучи в той же лодке и раньше.

Я работаю с Stripes без пружины и создал ручной фильтр, прежде чем он будет работать хорошо. Как вы уже упоминали, кодирование логики транзакций на бэкэнде становится очень быстрым. С нетерпением извлекать все становится УЖАСНЫМ, когда вы отображаете все больше и больше объектов друг на друга.

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

С помощью Stripersist вы можете произносить такие вещи, как /appContextRoot/actions/view/3, и он будет автоматически гидратировать сущность JPA в ActionBean с идентификатором 3 перед выполнением события.

Stripersist находится в пакете stripes-stuff на sourceforge . Теперь я использую это для всех новых проектов, так как он чистый и при необходимости легко поддерживает несколько источников данных.

1 голос
/ 04 декабря 2009

Хотя есть некоторые преимущества подхода DTO. Вы должны заранее подумать, какая информация вам нужна. В некоторых случаях это помешает вам создать n + 1 оператор выбора. Это также помогает увидеть, где использовать активные выборки и / или оптимизированные представления.

0 голосов
/ 04 декабря 2009

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

Что касается использования DTO, это может быть жизнеспособной реализацией. Если ваш бизнес-уровень используется внутренне вашим собственным приложением (т.е. небольшим веб-приложением и его бизнес-логикой), вероятно, было бы лучше использовать ваши собственные сущности в вашем представлении с открытым шаблоном представления в сеансе, поскольку это проще.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...