Открыть сессию в шаблоне просмотра
Я задаю этот вопрос, учитывая мои выбранные рамки разработки JPA (реализация Hibernate), Spring и < вставка структуры MVC здесь - Struts 1, Struts 2, Spring MVC, Stripes... > ;.
Я немного думал о связях в моем уровне сущности - например, у меня есть сущность заказа, которая имеет много строк заказа. Я настроил свое приложение так, чтобы он охотно загружал строки заказов для каждого заказа. Считаете ли вы, что это ленивый способ обойти ленивые проблемы с инициализацией, с которыми я столкнулся бы, если бы мне нужно было установить стратегию получения false?
Как я вижу это, у меня есть следующие альтернативы при извлечении сущностей и их ассоциаций:
-
Используйте шаблон Open Session In View для создания сеанса для каждого запроса и фиксации транзакции перед возвратом ответа.
-
Внедрить DTO (объект передачи данных), чтобы каждый выполняемый мной запрос DAO возвращал правильно инициализированный DTO для моих целей. Мне не очень нравится этот вариант, потому что, по моему опыту, я обнаружил, что он создает много кода копирования кода и становится беспорядочным для поддержки.
-
Не сопоставляйте какие-либо ассоциации в JPA, чтобы каждый выполняемый мной запрос возвращал только объекты, которые меня интересуют, - это, вероятно, потребует от меня иметь DTO в любом случае и будет болью для поддержания, и я думаю, что поражения цель иметь ORM в первую очередь.
-
Ищите все (или большинство ассоциаций) - в приведенном выше примере всегда извлекайте все строки порядка, когда я получаю заказ.
Итак, мой вопрос в том, когда и при каких обстоятельствах вы бы использовали какой из этих вариантов? Вы всегда придерживаетесь одного способа сделать это?
Я бы попросил коллегу, но я думаю, что, если бы я даже упомянул термин "Открытая сессия в представлении", меня бы приветствовали пустые взгляды: (Что я действительно ищу здесь, это советы старшего или очень опытного разработчик.
Спасибо, ребята!
Ответы
Ответ 1
Я успешно решил все свои ленивые проблемы с инициализацией с помощью Open Session In View -pattern (т.е. реализации Spring). Технологии, которые я использовал, были такими же, как и у вас.
Использование этого шаблона позволяет мне полностью сопоставить отношения сущности и не беспокоиться о получении дочерних объектов в dao. В основном. В 90% случаев шаблон решает ленивые потребности в инициализации в представлении. В некоторых случаях вам придется "вручную" инициализировать отношения. Эти случаи были редкими и всегда включали очень сложные отображения в моем случае.
При использовании шаблона Open Entity Manager In View важно правильно определить отношения сущностей и, особенно, параметры распространения и транзакции. Если они не настроены должным образом, будут возникать ошибки, связанные с закрытыми сеансами, когда какой-либо объект лениво инициализируется в представлении, и он выходит из строя из-за того, что сеанс уже закрыт.
Я определенно поеду с опцией 1. Иногда может понадобиться вариант 2, но я не вижу абсолютно никакой причины использовать опцию 3. Вариант 4 тоже нет. Ужасное извлечение всего убивает производительность любого представления, которое должно отображать только несколько свойств некоторых родительских объектов (порядки в этом случае).
N + 1 Выбирает
Во время разработки будет выбран N + 1 в результате инициализации некоторых отношений в представлении. Но это не повод отказаться от шаблона. Просто исправьте эти проблемы по мере их возникновения и перед тем, как доставить код в производство. Как легко устранить эти проблемы с шаблоном OEMIV, как и с любым другим шаблоном: добавьте правильные методы dao или службы, исправьте контроллер для вызова другого метода поиска, возможно, добавьте представление в базу данных и т.д.
Ответ 2
В открывшемся сеансе в представлении есть некоторые проблемы.
Например, , если транзакция терпит неудачу, вы можете узнать ее слишком поздно во время фиксации, как только вы почти выполнили рендеринг своей страницы (возможно, ответ уже завершен, поэтому вы не можете изменить page!)... Если раньше вы знали эту ошибку, вы бы следовали за другим потоком и заканчивали показ другой страницы...
В другом примере чтение данных по запросу может привести ко многим "N + 1 select" проблемам, которые убьют вашу производительность.
Во многих проектах используется следующий путь:
- Поддержание транзакций на бизнес-уровне; загрузите в этот момент все, что вам нужно.
- Уровень представления запускает риск LazyExceptions: каждый считается ошибкой программирования, пойманной во время тестов, и исправляется загрузкой большего количества данных в бизнес-уровне (у вас есть возможность сделать это эффективно, избегая "N + 1 select" ).
Чтобы избежать создания дополнительных классов для DTO, вы можете загружать данные внутри самих объектов сущности. В этом весь смысл подхода POJO (использование современными уровнями доступа к данным и даже интеграционные технологии, такие как Spring).
Ответ 3
Я успешно использовал шаблон Open-Session-in-View в проекте. Тем не менее, я недавно прочитал в "Spring In Practice" интересную потенциальную проблему с неповторяющимися чтениями, если вы управляете своими транзакциями на более низком уровне, сохраняя сеанс Hibernate открытым на уровне представления.
Мы выполнили большую часть наших транзакций на уровне сервиса, но сохранили сеанс hibernate открытым в слое представления. Это означало, что ленивые чтения в представлении приводили к отдельным транзакциям чтения.
Мы выполнили наши транзакции на нашем уровне обслуживания, чтобы свести к минимуму продолжительность транзакции. Например, некоторые из наших вызовов службы привели к транзакции базы данных и вызову веб-службы внешней службе. Мы не хотели, чтобы наша транзакция была открытой, ожидая ответа на вызов веб-службы.
Поскольку наша система никогда не входила в производство, я не уверен, были ли с ней какие-то реальные проблемы, но я подозреваю, что существует вероятность того, что представление попытается лениво загрузить объект, который был удален кем-то другим.
Ответ 4
Однако есть некоторые преимущества подхода DTO. Вы должны заранее подумать, какую информацию вам нужно. В некоторых случаях это предотвратит создание команд n + 1 select. Это также помогает увидеть, где использовать желаемые выборки и/или оптимизированные представления.
Ответ 5
Я также подниму свой вес за шаблон Open-Session-in-View, находясь на той же самой лодке раньше.
Я работаю с Stripes без spring, и создал ручной фильтр, прежде чем он будет работать хорошо. Кодирование логики транзакций на бэкэнде становится очень быстрым, как вы уже упоминали. Ужасное извлечение всего становится TERRIBLE, поскольку вы накладываете все больше и больше объектов друг на друга.
Одна вещь, которую я хочу добавить, что вы, возможно, не столкнулись, - это Stripersist и Stripernate - Stripersist, являющийся тем более ароматом JPA - фильтрами автогидратации, которые занимают много работы с ваших плеч.
С помощью Stripersist вы можете сказать такие вещи, как /appContextRoot/actions/view/3
, и он автоматически увлажнит объект JPA на ActionBean с идентификатором 3 до того, как будет выполнено событие.
Stripersist находится в пакете stripes-stuff на sourceforge. Теперь я использую это для всех новых проектов, поскольку он очищает и легко поддерживает несколько источников данных, если это необходимо.
Ответ 6
Строки заказов и заказов составляют большой объем данных? Принимают ли они участие в онлайн-процессах, где требуется реакция в реальном времени? Если это так, вы можете подумать о том, что вы не используете целеустремленный выбор - это делает огромную разницу в производительности. Если количество данных невелико, нет никаких проблем при загрузке.
Об использовании DTO, это может быть жизнеспособной реализацией.
Если ваш бизнес-уровень используется внутренне вашим собственным приложением (т.е. Небольшим веб-приложением и его бизнес-логикой), вероятно, было бы лучше использовать ваши собственные сущности в вашем представлении с открытым сеансом в виде, поскольку он проще.
Если ваши объекты используются многими приложениями (например, бэкэнд-приложение, предоставляющее услугу в вашей корпорации), было бы интересно использовать DTO, так как вы не станете показывать свою модель своим клиентам. Выявление этого может означать, что вам будет сложнее реорганизовать вашу модель, поскольку это может означать нарушение контрактов с вашими клиентами. DTO сделает это проще, так как у вас есть еще один слой
абстракция. Это может быть немного странно, поскольку EJB3 теоретически устранит необходимость DTO.