<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    kapok

    垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      455 隨筆 :: 0 文章 :: 76 評論 :: 0 Trackbacks

    轉自:Potain 的BLOG

    OpenSessionInView

    Created by potian. Last edited by admin 61 days ago. Viewed 181 times.
    [edit] [attach]
    Hibernate的Lazy初始化1:n關系時,你必須保證是在同一個Session內部使用這個關系集合,不然Hiernate將拋出例外。

    另外,你不愿意你的DAO測試代碼每次都打開關系Session,因此,我們一般會采用OpenSessionInView模式。

    OpenSessionInViewFilter解決Web應用程序的問題

    如果程序是在正常的Web程序中運行,那么Spring的OpenSessionInViewFilter能夠解決問題,它:

    protected void doFilterInternal(HttpServletRequest request, 
                 HttpServletResponse response,
    	     FilterChain filterChain) throws ServletException, IOException {
    	SessionFactory sessionFactory = lookupSessionFactory();
    	logger.debug("Opening Hibernate Session in OpenSessionInViewFilter");
    	Session session = getSession(sessionFactory);
    	TransactionSynchronizationManager.bindResource(sessionFactory, 
                 new SessionHolder(session));
    	try {
    		filterChain.doFilter(request, response);
    	}
    	finally {
    		TransactionSynchronizationManager.unbindResource(sessionFactory);
    		logger.debug("Closing Hibernate Session in OpenSessionInViewFilter");
    		closeSession(session, sessionFactory);
    	}
    }
    可以看到,這個Filter在request開始之前,把sessionFactory綁定到TransactionSynchronizationManager,和這個SessionHolder相關。這個意味著所有request執行過程中將使用這個session。而在請求結束后,將和這個sessionFactory對應的session解綁,并且關閉Session。

    為什么綁定以后,就可以防止每次不會新開一個Session呢?看看HibernateDaoSupport的情況:

    public final void setSessionFactory(SessionFactory sessionFactory) {
        this.hibernateTemplate = new HibernateTemplate(sessionFactory);
      }
     protected final HibernateTemplate getHibernateTemplate() {
      return hibernateTemplate;
     }

    我們的DAO將使用這個template進行操作:

    public abstract class BaseHibernateObjectDao
    	extends HibernateDaoSupport
    	implements BaseObjectDao {

    protected BaseEntityObject getByClassId(final long id) { BaseEntityObject obj = (BaseEntityObject) getHibernateTemplate() .execute(new HibernateCallback() {

    public Object doInHibernate(Session session) throws HibernateException { return session.get(getPersistentClass(), new Long(id)); }

    }); return obj; }

    public void save(BaseEntityObject entity) { getHibernateTemplate().saveOrUpdate(entity); }

    public void remove(BaseEntityObject entity) { try {

    getHibernateTemplate().delete(entity); } catch (Exception e) { throw new FlexEnterpriseDataAccessException(e); } }

    public void refresh(final BaseEntityObject entity) { getHibernateTemplate().execute(new HibernateCallback() {

    public Object doInHibernate(Session session) throws HibernateException { session.refresh(entity); return null; }

    }); }

    public void replicate(final Object entity) { getHibernateTemplate().execute(new HibernateCallback() {

    public Object doInHibernate(Session session) throws HibernateException { session.replicate(entity, ReplicationMode.OVERWRITE); return null; }

    }); }

    而HibernateTemplate試圖每次在execute之前去獲得Session,執行完就力爭關閉Session
    public Object execute(HibernateCallback action) throws DataAccessException {
    	Session session = (!this.allowCreate ?
    		SessionFactoryUtils.getSession(getSessionFactory(), 
                      false) :
    		SessionFactoryUtils.getSession(getSessionFactory(),
                      getEntityInterceptor(),
                      getJdbcExceptionTranslator()));
    	boolean existingTransaction =  
              TransactionSynchronizationManager.hasResource(getSessionFactory());
    	if (!existingTransaction && getFlushMode() == FLUSH_NEVER) {
    		session.setFlushMode(FlushMode.NEVER);
    	}
    	try {
    		Object result = action.doInHibernate(session);
    		flushIfNecessary(session, existingTransaction);
    		return result;
    	}
    	catch (HibernateException ex) {
    		throw convertHibernateAccessException(ex);
    	}
    	catch (SQLException ex) {
    		throw convertJdbcAccessException(ex);
    	}
    	catch (RuntimeException ex) {
    		// callback code threw application exception
    		throw ex;
    	}
    	finally {
    		SessionFactoryUtils.closeSessionIfNecessary(
                        session, getSessionFactory());
    	}
    }
    而這個SessionFactoryUtils能否得到當前的session以及closeSessionIfNecessary是否真正關閉session,端取決于這個session是否用sessionHolder和這個sessionFactory在我們最開始提到的TransactionSynchronizationManager綁定。
    public static void closeSessionIfNecessary(Session session, 
        SessionFactory sessionFactory)   
        throws CleanupFailureDataAccessException {
    	if (session == null || 
    	   TransactionSynchronizationManager.hasResource(sessionFactory)) {
    		return;
    	}
    	logger.debug("Closing Hibernate session");
    	try {
    		session.close();
    	}
    	catch (JDBCException ex) {
    		// SQLException underneath
    		throw new CleanupFailureDataAccessException(
    		"Cannot close Hibernate session", ex.getSQLException());
    	}
    	catch (HibernateException ex) {
    		throw new CleanupFailureDataAccessException(
    		"Cannot close Hibernate session", ex);
    	}
    }

    HibernateInterceptor和OpenSessionInViewInterceptor的問題

    使用同樣的方法,這兩個Interceptor可以用來解決問題。但是關鍵的不同之處在于,它們的力度只能定義在DAO或業務方法上,而不是在我們的Test方法上,除非我們把它們應用到TestCase的方法上,但你不大可能為TestCase去定義一個接口,然后把Interceptor應用到這個接口的某些方法上。直接使用HibernateTransactionManager也是一樣的。因此,如果我們有這樣的測試:

    Category parentCategory  = new Category ();
    	parentCategory.setName("parent");
    	dao.save(parentCategory);

    Category childCategory = new Category(); childCategory.setName("child");

    parentCategory.addChild(childCategory); dao.save(childCategory);

    Category savedParent = dao.getCategory("parent"); Category savedChild = (Category ) savedParent.getChildren().get(0); assertEquals(savedChild, childCategory);

    將意味著兩件事情:
    • 每次DAO執行都會啟動一個session和關閉一個session
    • 如果我們定義了一個lazy的關系,那么最后的Category savedChild = (Category ) savedParent.getChildren().get(0);將會讓hibernate報錯。

    解決方案

    一種方法是對TestCase應用Interceptor或者TransactionManager,但這個恐怕會造成很多麻煩。除非是使用增強方式的AOP.我前期采用這種方法(Aspectwerkz),在Eclipse里面也跑得含好。

    另一種方法是在TestCase的setup和teardown里面實現和Filter完全一樣的處理,其他的TestCase都從這個TestCase繼承,這種方法是我目前所使用的。

    posted on 2005-05-23 23:40 笨笨 閱讀(445) 評論(0)  編輯  收藏 所屬分類: J2EEHibernateAndSpringALL
    主站蜘蛛池模板: 久久永久免费人妻精品| 日韩毛片一区视频免费| 免费看又黄又无码的网站| 中文字幕日韩亚洲| 两性色午夜视频免费播放| 久久久久久A亚洲欧洲AV冫| 视频免费1区二区三区| 大胆亚洲人体视频| 一级特黄a免费大片| 亚洲人成无码网站| 最近中文字幕免费大全| 亚洲成年人在线观看| 免费观看激色视频网站bd | 久久免费国产视频| 亚洲精品福利网站| 我要看免费的毛片| 免费高清A级毛片在线播放| 亚洲男人的天堂在线va拉文| 精品乱子伦一区二区三区高清免费播放 | 亚洲国产片在线观看| 最近中文字幕免费mv视频8| 精品亚洲成a人在线观看| 亚洲精品综合久久| 久久久久国产精品免费免费不卡 | 中文字幕久久亚洲一区| 99精品视频在线观看免费专区| 91嫩草亚洲精品| 日韩免费在线观看| 中文字幕乱码系列免费| 亚洲最大视频网站| 国产免费资源高清小视频在线观看| 一级毛片视频免费观看| 亚洲精品午夜在线观看| 国产成人高清精品免费鸭子| 国产中文字幕在线免费观看| 亚洲天堂电影在线观看| 全部免费a级毛片| 51视频精品全部免费最新| 亚洲暴爽av人人爽日日碰| 国产亚洲精品福利在线无卡一 | 国产免费怕怕免费视频观看|