NHibernate + MVC + Spring. Динамические объекты (через Activator.CreateInstance) с HibernateTemplate (инициализируется Spring) вызывают исключение отложенной загрузки - PullRequest
0 голосов
/ 28 декабря 2011

Структура моего веб-приложения следующая: У меня есть классы DAO (для каждого конкретного экземпляра), унаследованные от BaseDAO<T, TId>. (Где T может быть что-то вроде «Клиенты»). Базовый класс содержит свойство HibernateTemplate.

У меня есть базовый класс для контроллеров MVC (с унаследованными).

У меня есть базовый класс для Service (модель сервиса M + V + C +) (с унаследованными единицами для экземпляра (например, «CustomersService»)).

У меня есть базовый класс для класса DAO (с унаследованными в каждом экземпляре ...) (разделенный в другом проекте VS).

У меня есть классы объектов POCO (для каждой таблицы базы данных), отображения (и отношения между которыми) определены в XML-файле для Hibernate.

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

  • Контроллеры MVC включают некоторые служебные свойства (которые необходимы для работы контроллеров) и инициализируются Spring через определения XML-файлов. (например, UsersController может иметь свойства UsersService и UsersRolesServices)

  • Каждый сервис включает соответствующее свойство DAO-helper (например, UsersService имеет свойство UsersDAO), инициализация которого также определена в файле xml (для Spring).

Итак, в общем случае (поскольку каждая такая инициализация определяется в файле xml) вся эта структура инициализируется Spring в начале жизненного цикла страницы. И все работает хорошо. ... кроме удобства процесса разработки ... поскольку мне нужно заранее определить "все везде", т. е. скажем, на случай, если мне понадобится также UsersWearService в UsersController, тогда я должен определить его свойство в UsersController и перейдите в XML-файл и добавьте его инициализацию. Так что это так неудобно и негибко.

Что я пытался сделать:

Я создал метод GetService<UsersService>().GetAllUsers() (только пример) который создает сервис динамически через Activator.CreateInstance (он позволяет вызывать любой сервис на любом контроллере без какого-либо предварительного определения). Все было хорошо, за исключением того, что у меня не было HibernateTemplate (== null) (так как он не был "активирован" через Spring). Поэтому я попытался получить этот объект через Application.Current.Context и GetObject, чтобы получить шаблон HibernateTemplate через Spring + Hibernate.

Все даже начало работать, но только с простыми запросами.

Если я попытаюсь сделать что-то вроде этого:

GetService<UsersService>()
    .GetAllUsers()
    .Where(x => x.UsersEmailsAmount.Count > 0) 

(при ленивой загрузке дочерних коллекций)

... он получает следующее исключение:

«Не удалось лениво инициализировать коллекцию - ни один сеанс или сеанс не был закрыт».

После всего этого я даже попытался добавить какое-то свойство в Controller / Service / Dao (к базовому классу) (которое должно было бы определять только Controller в файле XML-файла гибернации), и я даже получил свойство HibernateTemplate, хорошо инициализированное, но в этой ленивой операции загрузки у меня все то же исключение.

Кажется, в случае такой динамической загрузки "что-то", "где-то" все еще не инициализирована ссылка на сессию (даже если я получаю объект HibernateTemplate через Spring), но я не знаю, где это "что-то" и "где-то" , Я чувствую, что все это происходит вокруг объектов POCO с некоторым внутренним поведением Hibernate, но я не могу видеть, как все эти вещи связаны друг с другом.

Может кто-нибудь дать мне хоть какую-нибудь подсказку, что с этим не так, или даже если теоретически возможно реализовать то, что я хотел? (Я верю, что все, что можно сделать в разработке, но вопрос, стоит ли это того времени).

Я новичок в hibernate, и ребята, которые разрабатывали это приложение, готовы тратить столько времени на все эти определения, но это так неудобно и не так очевидно (даже не говоря о новых разработчиках (особенно без какой-либо документации!) )

Ответы [ 3 ]

0 голосов
/ 28 декабря 2011

После некоторых исследований я обнаружил, что в моем "динамически созданном DAO" вызове HibernateTemplate.SessionFactory.GetCurrentSession () выбрасывается следующее исключение:

Нет привязки Hibernate к потоку и конфигурацииздесь не разрешено создание нетранзакционного.

Я читал некоторые форумы, и в некоторых случаях они предлагают просто определить раздел управления транзакциями для файлов конфигурации или добавить некоторые атрибуты для методов DAO, например"@Transactional".

Но есть много ответов, но они относятся не к NHibernate (а к обычным Java)!Итак, у меня до сих пор нет никаких решений.

0 голосов
/ 29 декабря 2011

После некоторых исследований я обнаружил, что то, что я пытаюсь сделать, довольно сложно (по крайней мере, в моей ситуации с проектом, так как мне не разрешают сильно меняться).Для любых людей, которые постараются «воплотить мою мечту» (в своих проектах), могу сказать, что все возможно.Я вижу возможность реализовать это, написав свой собственный класс SessionContext (возможно, унаследованный от SpringSessionContext) и определить его в current_session_context_class, чтобы он мог выполнять следующие действия: CurrentSessionContext.Bind (в настоящее время это невозможно из-за ограничений SpringSessionContext).Но в этом случае он должен быть определен в файле конфигурации NHibernate вне инфраструктуры Spring.NET, что является проблемой "..."

Это действительно говорит о том, что Spring.NET используется в нашем проекте.Я полностью .NET-разработчик и хорошо знаю C #, поэтому особенно в последних выпусках .NET Framework я вижу все меньше и меньше причин использовать Spring.NET для веб-проектов MVC (что на самом деле подтверждается очень небольшим количеством документации и информации).на форумах (относительно небольших, конечно)).Я считаю, что «XML-определенное программирование» далеко не для процесса разработки .NET (особенно с использованием MS VS + Resharper).Я знаю много ребят, которые сказали бы: «О, это не проблема для меня, чтобы определить все эти вещи в XML», и я могу понять их, но такой подход не подходит для больших проектов, особенно для поддержки, особенно если приходят новые людик процессу разработки.Я не фанат Microsoft, но то, что MS делает с .NET, действительно здорово и удобно.

А также, если бы кто-то прочитал эти строки, я бы рекомендовал всегда использовать «NHibernate».»как термины« NHibernate »и« Spring.NET »в публикациях и комментариях к этому, потому что, когда вы пытаетесь искать в поисковых системах на .NET конкретно - это та же« боль в ... », чтобы найти что-нибудь относительное.

Спасибо!

0 голосов
/ 28 декабря 2011

Интересно.Кажется, разработчики хотели использовать все интересные вещи в этом проекте сразу.

Что вам нужно исследовать, так это жизненный цикл сеанса nhibernate.

  • Когда он открывается?
  • Когда он закрывается?
  • Загружает ли Spring сервисы за один раз или за вызов части страницы, как, например, ajax, что может повлиять на сеанс?Зависимости проясняются или вы еще больше застряли в грязи?
  • Существуют ли какие-либо входные и / или выходные фильтры, открывают они или закрывают, очищают сеанс?

Удачи.

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