最后更新时间:2007-05-17 关键字: spring 多数据库 事务 hibernate
假设,我配置了两个sessionFatory ,一个是mitSessionFactory,一个是testSessionFactory,如下:
xml 代码
- <hibernatesupport>
- <item id="mit" bean="mitSessionFactory"/>
- <item id="test" bean="testSessionFactory"/>
- hibernatesupport>
这个我自己系统配置的一部分,系统会解析他,从而知晓究竟存在多少个sessionFactory,item's XmlNode中的id可以理解会托管客户的客户单位
编号,当然,这个配置完全可以忽略,直接从ApplicationContext中一样可以获取到这样的信息
在客户登陆的时候,系统要记录下该客户所属托管单位,然后通过上面的id找到bean's name ,最后获取这个sessionFactory,托管单位信息一般
都是个编号而已跟己方系统的托管用户管理相结合,一般是保存这个编号在session里面,也可以象asp.net一样,记录在安全凭证里,还不知道JAVA方面有没有类似实现,个人认为asp.net这个方法很值得采用,虽然MS号称安全系数+++++这个观点值得怀疑
首先建立一个类,HibernateSupport ,存放当前请求线程所需sessionFactory
java 代码
- public class HibernateSupport {
- public static final String HIBERNATE_SESSIONIDKEY = "com.mit.hibernatesupport.factory.id";
- private static final Logger logger = Logger.getLogger(HibernateSupport.class);
- private static ApplicationContext applicationContext ;
- private static boolean singleSession=true;
- private static Map factorybeanset;
- private static ThreadLocal switchhistory;
- private static ThreadLocal idset;
- private static ThreadLocal curfactory;
- private static ThreadLocal trace;
- static
- {
- idset = new ThreadLocal();
- curfactory = new ThreadLocal();
- trace = new ThreadLocal();
- switchhistory = new ThreadLocal();
- }
-
-
-
-
-
-
- public static synchronized void setCurrent(ServletContext context,Object id)
- {
- if (idset.get()==null)
- {
- idset.set(id);
- if (factorybeanset.containsKey(id))
- {
- if (applicationContext==null)
- {
- applicationContext =
- WebApplicationContextUtils
- .getWebApplicationContext(context);
- }
- curfactory.set((SessionFactory)applicationContext
- .getBean((String)factorybeanset.get(id)));
- putTrace(idset.get(),(SessionFactory)curfactory.get());
- }
- }
- }
-
-
-
-
-
-
-
- private static void putTrace(Object id ,SessionFactory factory)
- {
- Map tracemap = null;
- if (trace.get()==null)
- {
- tracemap = new HashMap();
- trace.set(tracemap);
- }
- else
- {
- tracemap = (Map)trace.get();
- }
- if (!tracemap.containsKey(id))
- {
- tracemap.put(id, factory);
- }
- }
-
-
-
-
-
- public static synchronized void swtichFactory(Object id)
- {
- if (!idset.get().equals(id) )
- {
- if (factorybeanset.containsKey(id))
- {
- SessionFactory oldfactory = (SessionFactory)curfactory.get();
- SessionFactory newfactory = (SessionFactory)applicationContext
- .getBean((String)factorybeanset.get(id));
- curfactory.set(newfactory);
- pushHistory(oldfactory);
- putTrace(id,newfactory);
- bindSessionFactory(newfactory);
- }
- }
- }
-
-
-
-
- public static synchronized void restoreFactory()
- {
- SessionFactory factory = popHistory();
- if (factory!=null)
- {
- curfactory.set(factory);
- }
- }
-
-
-
-
- private static void pushHistory(SessionFactory sessionfactory)
- {
- LinkedList list = null;
- if (switchhistory.get()==null)
- {
- list = new LinkedList();
- switchhistory.set(list);
- }
- else
- {
- list = (LinkedList)switchhistory.get();
- }
- list.add(0,sessionfactory);
-
- }
-
-
-
- private static SessionFactory popHistory()
- {
- if (switchhistory.get()!=null)
- {
- LinkedList list = (LinkedList)switchhistory.get();
- if (list.size()>0)
- {
- SessionFactory factory = (SessionFactory)list.getFirst();
- list.removeFirst();
- return factory;
- }
- }
- return null;
- }
-
- public static Map getTraceMap()
- {
- if (trace.get()!=null)
- {
- return (Map)trace.get();
- }
- return null;
- }
-
- public static SessionFactory getCurrentFactory()
- {
- return (SessionFactory)curfactory.get();
- }
-
- public static synchronized void release()
- {
- idset.set(null);
- curfactory.set(null);
- switchhistory.set(null);
- trace.set(null);
- }
-
-
-
-
-
- private static synchronized boolean bindSessionFactory(SessionFactory sessionFactory)
- {
- boolean participate=false;;
- if (singleSession) {
-
- if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
-
- participate = true;
- }
- else {
- logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter");
- Session session = getSession(sessionFactory);
- if (!TransactionSynchronizationManager.hasResource(sessionFactory))
- {
- TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
- }
- }
- }
- else {
-
- if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
-
- participate = true;
- }
- else {
- SessionFactoryUtils.initDeferredClose(sessionFactory);
- }
- }
- return participate;
- }
-
-
- private static Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
- Session session = SessionFactoryUtils.getSession(sessionFactory, true);
- FlushMode flushMode = FlushMode.COMMIT;
- if (flushMode != null) {
- session.setFlushMode(flushMode);
- }
- return session;
- }
-
- public static synchronized void initSessionFactory(Map res,Class loadclass)
- {
- factorybeanset =res;
- }
-
- public static void setSingleSession(boolean singleSession) {
- HibernateSupport.singleSession = singleSession;
- }
-
- }
-
-
- bindSessionFactory·½·¨ºÍgetSession¶¼ÊÇ´ÓspringÖ±½ÓCOPY¹ýÀ´µÄ¡£
- Õâ¸öÀàÆäËû·½·¨¿ÉÒÔ²»¹Ü£¬ÔÝʱ¹Ø×¢setCurrentÕâ¸ö·½·¨
- if (idset.get()==null)
- {
- idset.set(id);
- if (factorybeanset.containsKey(id))
- {
- if (applicationContext==null)
- {
- applicationContext =
- WebApplicationContextUtils
- .getWebApplicationContext(context);
- }
- curfactory.set((SessionFactory)applicationContext
- .getBean((String)factorybeanset.get(id)));
- putTrace(idset.get(),(SessionFactory)curfactory.get());
- }
- }
- HibernateSupportFilterÊǸöservlet filter,Ëû»á»ñÈ¡µ±Ç°ÇëÇóµÄÍйÜÓû§±àºÅÈ»ºóµ÷ÓÃsetCurrent
-
- public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
- HttpSession session = ((HttpServletRequest)req).getSession();
- if (session.getAttribute(HibernateSupport.HIBERNATE_SESSIONIDKEY)!=null)
- {
- Object id = session.getAttribute(HibernateSupport.HIBERNATE_SESSIONIDKEY);
- if (log.isDebugEnabled())
- {
- log.debug("Set Current SessionFactory:"+id.toString());
- }
- HibernateSupport.setCurrent(config.getServletContext(),session.getAttribute(HibernateSupport.HIBERNATE_SESSIONIDKEY));
- }
- try
- {
- chain.doFilter(req, res);
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- }
- finally
- {
- HibernateSupport.release();
- }
- }
这个类其他方法可以不管,暂时关注setCurrent这个方法
java 代码
- if (idset.get()==null)
- {
- idset.set(id);
- if (factorybeanset.containsKey(id))
- {
- if (applicationContext==null)
- {
- applicationContext =
- WebApplicationContextUtils
- .getWebApplicationContext(context);
- }
- curfactory.set((SessionFactory)applicationContext
- .getBean((String)factorybeanset.get(id)));
- putTrace(idset.get(),(SessionFactory)curfactory.get());
- }
- }
HibernateSupportFilter是个servlet filter,他会获取当前请求的托管用户编号然后调用setCurrent
java 代码
- public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
- HttpSession session = ((HttpServletRequest)req).getSession();
- if (session.getAttribute(HibernateSupport.HIBERNATE_SESSIONIDKEY)!=null)
- {
- Object id = session.getAttribute(HibernateSupport.HIBERNATE_SESSIONIDKEY);
- if (log.isDebugEnabled())
- {
- log.debug("Set Current SessionFactory:"+id.toString());
- }
- HibernateSupport.setCurrent(config.getServletContext(),session.getAttribute(HibernateSupport.HIBERNATE_SESSIONIDKEY));
- }
- try
- {
- chain.doFilter(req, res);
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
- }
- finally
- {
- HibernateSupport.release();
- }
- }
然后,就要修改spring关于hibernate的一些支持类了,当然,也可以选择重新写一套dao支持类,呵呵,不过,显然,在spring基础上做一些小修改代价更小
HibernateAccessor (HibernateTemplate的基类)以及HibernateTransactionManager都是靠注入方式获取一个sessionFactory,显然,这套不适合了,修改之