Где открывать сессии в стеке Spring / Hibernate? - PullRequest
5 голосов
/ 19 мая 2010

Я пытаюсь найти хороший дизайн для приложения Spring / Hibernate. При создании такого приложения создается впечатление, что существует несколько важных решений.

Первое важное решение, по-видимому, заключается в том, где поставить границу сеанса / транзакции. Похоже, у меня есть 3 основных варианта: в качестве фильтра до того, как контроллеры даже будут вызваны, непосредственно под контроллерами на уровне сервисных вызовов и заполнены намного ниже бизнес-уровня в вызовах репозитория.

Мне кажется, что правильный вызов - это средний путь, но я не уверен. Я не хочу, чтобы мои транзакции открывались слишком долго, но в то же время я не хочу постоянно беспокоиться об отделенных объектах и ​​ленивой загрузке в бизнес-логике. Тем не менее, есть некоторые недостатки. Например, бизнес-логике сложно выполнять удаленный вызов без удержания транзакции в течение нескольких секунд. Интересно, есть ли лучший способ?

Ответы [ 2 ]

1 голос
/ 19 мая 2010

Решение 1: открыть сеанс в виде фильтра

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

Решение 2: границы транзакций на бизнес-уровне

  • Преимущества:
    • Больше гибкости на уровне контроллера (но это может быть проклятием, если у вас есть члены вашей команды, которые на самом деле не понимают транзакции и размещают слишком много логики на уровне контроллера, используя несколько tx там, где должен был быть только один)
    • меньшее использование ресурсов (поскольку вы быстрее возвращаете соединения дБ в пул)
  • Недостатки:
    • Вам нужно будет осторожно использовать объект вашей модели, когда вы находитесь за пределами уровня транзакций. Самый простой способ избежать исключения lazyInitialization - это, возможно, использовать DTO, и каждый сервис реализует два интерфейса (один расширяет другой): один, содержащий только методы, возвращающие DTO, и другие только методы, возвращающие объекты вашей модели. Первый интерфейс вы будете использовать в декларациях в контроллере, а второй - только на бизнес-уровне, где транзакция все еще открыта, поэтому возврат объекта модели не может привести к исключению отложенной инициализации.

Решение 3: границы транзакций на слое dao

Если ваши методы dao не содержат бизнес-логику, бессмысленно ограничивать транзакцию вызовом dao. Я думаю, это способ закрыть режим 'autocommit', чтобы быть полезным.


В любом случае, если вы хотите, чтобы ваша транзакция была короткой, я советую вам внимательно следить за «sql footprint» каждого бизнес-сценария (установив для категории журнала org.hibernate.SQL значение DEBUG) и сравнить произведенные sql с тем, что вы бы написали сами.

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

1 голос
/ 19 мая 2010

Это зависит от того, как вы модулировали код. Я предполагаю, что вы не написали весь код, связанный с транзакциями БД, в своих контроллерах. В случае, если вы разделили свой код на уровень DAO или Service, который заботится о транзакциях, имеет смысл иметь степень детализации только столько, сколько требуется.

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

Если вышеприведенное не применимо, тогда граница транзакции / сеанса может быть ограничена только уровнем доступа к данным.

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