Как получить сессию Hibernate внутри перехватчика Hibernate? - PullRequest
6 голосов
/ 08 января 2009

Как получить сеанс Hibernate внутри перехватчика Hibernate?

Я пытаюсь использовать Hibernate для прозрачного обеспечения доступа к данным по идентификатору организации. Я установил глобальный фильтр для фильтрации всех запросов по идентификатору организации. Теперь мне нужно использовать перехватчик сущностей, чтобы установить организационный идентификатор для всех сущностей перед сохранением / обновлением.

Идентификатор организации приходит из HttpSession

Я установил Organizational Id в качестве свойства фильтра в сеансе Hibernate, который я хочу получить внутри моего перехватчика и использовать для всех вставок и обновлений. Проблема в том, что у меня нет доступа к сеансу внутри перехватчика. Есть ли обходные пути для этого?

Ответы [ 4 ]

2 голосов
/ 09 января 2009

Можно, но я бы использовал простой POJO только для того, чтобы все было четко разделено. Имейте в виду, что значение, хранящееся в синглтоне, будет доступно только тому же потоку, который обработал запрос сервлета, поэтому, если вы делаете какую-либо асинхронность, вам нужно будет это учитывать. Вот супер базовый импл:

public class OrgId {
   public static ThreadLocal<Integer> orgId = new ThreadLocal<Integer>();
}

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

public class OrgIdFilter implements Filter {
   public void doFilter(ServletRequest servletrequest, ServletResponse servletresponse, FilterChain filterchain) throws java.io.IOException, javax.servlet.ServletException {
      int orgId = 0;
      HttpServletRequest req = (HttpServletRequest) servletRequest;
      HttpSession session = req.getSession();
      orgId = Integer.parseInt(session.getAttribute("OrganizationalIdAttr"));
      try {
         OrgId.orgId.set(orgId);
         filterChain.doFilter(servletRequest, servletresponse);
      } finally {
         OrgId.orgId.set(null); // Important to clear after request !!
      }
   }
}

Предполагается, что orgId находится в сеансе, когда вызывается фильтр, но если нет, вы понимаете ...

Тогда в вашем перехватчике (или почти везде) вы можете получить текущий orgId потока с помощью:

OrgId.orgId.get();   // Might be null.....

Потенциальный snafu здесь заключается в том, что все эти компоненты (фильтр, OrgId и перехватчик) должны быть загружены одним и тем же загрузчиком классов, чтобы гарантировать, что класс OrgId фактически является одиночным, в противном случае с множеством экземпляров ThreadLocal, висящих вокруг не будет работать последовательно или вообще. Излишне говорить, что все это должно происходить в одной и той же виртуальной машине.

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

2 голосов
/ 10 января 2009

Когда вы создаете свой перехватчик, если вы можете предоставить ему ссылку на SessionFactory, вы можете использовать SessionFactory # getCurrentSession

2 голосов
/ 08 января 2009

Если вам нужен только организационный идентификатор, вы можете поместить его в статический ThreadLocal и затем получить к нему доступ в перехватчике.

С другой стороны, если вы не можете получить сессию, и это зависит от среды, в которой вы находитесь, вы можете отказаться от перехватчика и использовать org.hibernate.event.FlushEntityEventListener, который, в любом случае, больше соответствует потребностям , Вы можете получить сеанс так (грубый псевдокод):

FlushEntityEventListener.onFlushEntity(FlushEntityEvent event)
EntityEvent entityEvent = event.getEntityEntry();
EntityPersister persister = entityEvent.getPersister();
SessionFactoryImplementor sessionFactoryImplor = persister.getFactory();
Session session = sessionFactoryImplor.getCurrentSession();

Из документов Hibernate 3 On Line : Систему событий можно использовать в качестве дополнения или замены перехватчиков.

0 голосов
/ 12 января 2009

Перехватчик может быть сделан. BeanFactoryAware и SessionFactory могут быть получены с использованием фабрики компонентов, из которой может быть получен текущий сеанс.

Поскольку это казалось плохим дизайном из-за циклической зависимости и информирования Interceptor о контейнере Spring, я использовал ThreadLocal, как предложил Николас

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