非web环境spring管理hibernate,延迟加载有关问题

非web环境spring管理hibernate,延迟加载问题
/*
 * @(#)HibernateLazyResolver.java
 *
 * Copyright 2009 Xinhua Online, Inc. All rights reserved.
 */

package com.winxuan.framework.util.hibernate;

import java.io.Serializable;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * 仿照openSessionInViewFilter,完成在非web环境下session打开
 * @version 1.0,2009-6-9
 */


public class HibernateLazyResolver implements Serializable{

	private static final long serialVersionUID = 4728620183698481396L;

	private static final Log LOG = LogFactory.getLog(HibernateLazyResolver.class);;

	private boolean singleSession = true; 

	private SessionFactory sessionFactory;

	boolean participate = false;

	protected Session session = null;
	   
	public final void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory=sessionFactory;
	}

	/**
	* Set whether to use a single session for each request. Default is true.
	* <p>If set to false, each data access operation or transaction will use
	* its own session (like without Open Session in View);. Each of those
	* sessions will be registered for deferred close, though, actually
	* processed at request completion.
	* @see SessionFactoryUtils#initDeferredClose
	* @see SessionFactoryUtils#processDeferredClose
	*/
	public void setSingleSession(boolean singleSession) {
		this.singleSession = singleSession;
	}

	/**
	* Return whether to use a single session for each request.
	*/
	protected boolean isSingleSession() {
		return singleSession;
	}

	/**
	 * 初始化 session, 在需要 lazy 的开始处调用
	 *
	 */
	public void openSession() {
		if (isSingleSession()) {
			// single session mode
			if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
				// Do not modify the Session: just set the participate flag.
				participate = true;
			}
			else {
				LOG.debug("Opening single Hibernate Session in HibernateLazyResolver");
				session = getSession(sessionFactory);
				TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
			}
		}
		else {
			// deferred close mode
			if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
				// Do not modify deferred close: just set the participate flag.
				participate = true;
			}
			else {
				SessionFactoryUtils.initDeferredClose(sessionFactory);
			}
		}
		
	}

	/**
	 * 释放 session, 在 lazy 的结束处调用
	 *
	 */
	public void releaseSession() {
		if (!participate){
			if (isSingleSession()) {
				// single session mode
				SessionHolder sessionHolder =
						(SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
				LOG.debug("Closing single Hibernate Session in HibernateLazyResolver");
				closeSession(sessionHolder.getSession(), sessionFactory);
			}
			else {
				// deferred close mode
				SessionFactoryUtils.processDeferredClose(sessionFactory);
			}
		}
	}
		
	/**
	 * Get a Session for the SessionFactory that this filter uses.
	 * Note that this just applies in single session mode!
	 * <p>The default implementation delegates to SessionFactoryUtils'
	 * getSession method and sets the Session's flushMode to NEVER.
	 * <p>Can be overridden in subclasses for creating a Session with a custom
	 * entity interceptor or JDBC exception translator.
	 * @param sessionFactory the SessionFactory that this filter uses
	 * @return the Session to use
	 * @throws DataAccessResourceFailureException if the Session could not be created
	 * @see org.springframework.orm.hibernate3.SessionFactoryUtils#getSession(SessionFactory, boolean);
	 * @see org.hibernate.FlushMode#NEVER
	 */
	protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
		Session session = SessionFactoryUtils.getSession(sessionFactory, true);
		session.setFlushMode(FlushMode.AUTO);
		return session;
	}

	/**
	 * Close the given Session.
	 * Note that this just applies in single session mode!
	 * <p>Can be overridden in subclasses, e.g. for flushing the Session before
	 * closing it. See class-level javadoc for a discussion of flush handling.
	 * Note that you should also override getSession accordingly, to set
	 * the flush mode to something else than NEVER.
	 * @param session the Session used for filtering
	 * @param sessionFactory the SessionFactory that this filter uses
	 */
	protected void closeSession(Session session, SessionFactory sessionFactory) {
		session.flush();
		SessionFactoryUtils.releaseSession(session, sessionFactory);
	}
	
	
}