`
dylan0514sina.cn
  • 浏览: 94946 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

SessionFactoryUtils

 
阅读更多
SessionFactoryUtils支持JTATransactionManager和HibernateTransactionManager;被Spring内部HibernateTemplate或HibernateInterceptor使用,同时可由应用代码调用。它提供了事务或非事务性Session获取,释放,Hibernate异常转换,事务超时等功能。下面介绍主要方法
  
  doGetSession

  如果SessionHolder中存在Session,则检测sessionHolder是否事务同步,否则注册同步;
  否则创建新的Session,注册同步并绑定线程
同步
  Spring同步激活状态下,使用Spring同步,同时设置FlushMode;
  否则Hibernate的javax.transaction.TransactionManager检测到激活的JTA事务,则使用JTA同步,同时设置FlushMode;这种情况下sessionMap放置key=javax.transaction.Transaction,value=Session
  否则不使用同步
FlushMode
  修改非只读事务(由definition指定)的FlushMode模式由FlushMode.Manual为FlushMode.AUTO,以至于事务提交时可Flush;待事务处理完成之后再回复。

/**
	 * Get a Hibernate Session for the given SessionFactory. Is aware of and will
	 * return any existing corresponding Session bound to the current thread, for
	 * example when using HibernateTransactionManager. Will create a new Session
	 * otherwise, if "allowCreate" is <code>true</code>.
	 * <p>Same as <code>getSession</code>, but throwing the original HibernateException.
	 * @param sessionFactory Hibernate SessionFactory to create the session with
	 * @param entityInterceptor Hibernate entity interceptor, or <code>null</code> if none
	 * @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
	 * Session on transaction synchronization (can be <code>null</code>)
	 * @param allowCreate if a non-transactional Session should be created when no
	 * transactional Session can be found for the current thread
	 * @return the Hibernate Session
	 * @throws HibernateException if the Session couldn't be created
	 * @throws IllegalStateException if no thread-bound Session found and
	 * "allowCreate" is <code>false</code>
	 */
	private static Session doGetSession(
			SessionFactory sessionFactory, Interceptor entityInterceptor,
			SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate)
			throws HibernateException, IllegalStateException {

		Assert.notNull(sessionFactory, "No SessionFactory specified");

		SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
		if (sessionHolder != null && !sessionHolder.isEmpty()) {
			// pre-bound Hibernate Session
			Session session = null;
			if (TransactionSynchronizationManager.isSynchronizationActive() &&
					sessionHolder.doesNotHoldNonDefaultSession()) {
				// Spring transaction management is active ->
				// register pre-bound Session with it for transactional flushing.
				session = sessionHolder.getValidatedSession();
				if (session != null && !sessionHolder.isSynchronizedWithTransaction()) {
					logger.debug("Registering Spring transaction synchronization for existing Hibernate Session");
					TransactionSynchronizationManager.registerSynchronization(
							new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false));
					sessionHolder.setSynchronizedWithTransaction(true);
					// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
					// with FlushMode.NEVER, which needs to allow flushing within the transaction.
					FlushMode flushMode = session.getFlushMode();
					if (flushMode.lessThan(FlushMode.COMMIT) &&
							!TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
						session.setFlushMode(FlushMode.AUTO);
						sessionHolder.setPreviousFlushMode(flushMode);
					}
				}
			}
			else {
				// No Spring transaction management active -> try JTA transaction synchronization.
				session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator);
			}
			if (session != null) {
				return session;
			}
		}

		logger.debug("Opening Hibernate Session");
		Session session = (entityInterceptor != null ?
				sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession());

		// Use same Session for further Hibernate actions within the transaction.
		// Thread object will get removed by synchronization at transaction completion.
		if (TransactionSynchronizationManager.isSynchronizationActive()) {
			// We're within a Spring-managed transaction, possibly from JtaTransactionManager.
			logger.debug("Registering Spring transaction synchronization for new Hibernate Session");
			SessionHolder holderToUse = sessionHolder;
			if (holderToUse == null) {
				holderToUse = new SessionHolder(session);
			}
			else {
				holderToUse.addSession(session);
			}
			if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
				session.setFlushMode(FlushMode.NEVER);
			}
			TransactionSynchronizationManager.registerSynchronization(
					new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true));
			holderToUse.setSynchronizedWithTransaction(true);
			if (holderToUse != sessionHolder) {
				TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);
			}
		}
		else {
			// No Spring transaction management active -> try JTA transaction synchronization.
			registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder);
		}

		// Check whether we are allowed to return the Session.
		if (!allowCreate && !isSessionTransactional(session, sessionFactory)) {
			closeSession(session);
			throw new IllegalStateException("No Hibernate Session bound to thread, " +
			    "and configuration does not allow creation of non-transactional one here");
		}

		return session;
	}

	/**
	 * Retrieve a Session from the given SessionHolder, potentially from a
	 * JTA transaction synchronization.
	 * @param sessionHolder the SessionHolder to check
	 * @param sessionFactory the SessionFactory to get the JTA TransactionManager from
	 * @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
	 * Session on transaction synchronization (can be <code>null</code>)
	 * @return the associated Session, if any
	 * @throws DataAccessResourceFailureException if the Session couldn't be created
	 */
	private static Session getJtaSynchronizedSession(
	    SessionHolder sessionHolder, SessionFactory sessionFactory,
	    SQLExceptionTranslator jdbcExceptionTranslator) throws DataAccessResourceFailureException {

		// JTA synchronization is only possible with a javax.transaction.TransactionManager.
		// We'll check the Hibernate SessionFactory: If a TransactionManagerLookup is specified
		// in Hibernate configuration, it will contain a TransactionManager reference.
		TransactionManager jtaTm = getJtaTransactionManager(sessionFactory, sessionHolder.getAnySession());
		if (jtaTm != null) {
			// Check whether JTA transaction management is active ->
			// fetch pre-bound Session for the current JTA transaction, if any.
			// (just necessary for JTA transaction suspension, with an individual
			// Hibernate Session per currently active/suspended transaction)
			try {
				// Look for transaction-specific Session.
				Transaction jtaTx = jtaTm.getTransaction();
				if (jtaTx != null) {
					int jtaStatus = jtaTx.getStatus();
					if (jtaStatus == Status.STATUS_ACTIVE || jtaStatus == Status.STATUS_MARKED_ROLLBACK) {
						Session session = sessionHolder.getValidatedSession(jtaTx);
						if (session == null && !sessionHolder.isSynchronizedWithTransaction()) {
							// No transaction-specific Session found: If not already marked as
							// synchronized with transaction, register the default thread-bound
							// Session as JTA-transactional. If there is no default Session,
							// we're a new inner JTA transaction with an outer one being suspended:
							// In that case, we'll return null to trigger opening of a new Session.
							session = sessionHolder.getValidatedSession();
							if (session != null) {
								logger.debug("Registering JTA transaction synchronization for existing Hibernate Session");
								sessionHolder.addSession(jtaTx, session);
								jtaTx.registerSynchronization(
										new SpringJtaSynchronizationAdapter(
												new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false),
												jtaTm));
								sessionHolder.setSynchronizedWithTransaction(true);
								// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
								// with FlushMode.NEVER, which needs to allow flushing within the transaction.
								FlushMode flushMode = session.getFlushMode();
								if (flushMode.lessThan(FlushMode.COMMIT)) {
									session.setFlushMode(FlushMode.AUTO);
									sessionHolder.setPreviousFlushMode(flushMode);
								}
							}
						}
						return session;
					}
				}
				// No transaction active -> simply return default thread-bound Session, if any
				// (possibly from OpenSessionInViewFilter/Interceptor).
				return sessionHolder.getValidatedSession();
			}
			catch (Throwable ex) {
				throw new DataAccessResourceFailureException("Could not check JTA transaction", ex);
			}
		}
		else {
			// No JTA TransactionManager -> simply return default thread-bound Session, if any
			// (possibly from OpenSessionInViewFilter/Interceptor).
			return sessionHolder.getValidatedSession();
		}
	}

	/**
	 * Register a JTA synchronization for the given Session, if any.
	 * @param sessionHolder the existing thread-bound SessionHolder, if any
	 * @param session the Session to register
	 * @param sessionFactory the SessionFactory that the Session was created with
	 * @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
	 * Session on transaction synchronization (can be <code>null</code>)
	 */
	private static void registerJtaSynchronization(Session session, SessionFactory sessionFactory,
			SQLExceptionTranslator jdbcExceptionTranslator, SessionHolder sessionHolder) {

		// JTA synchronization is only possible with a javax.transaction.TransactionManager.
		// We'll check the Hibernate SessionFactory: If a TransactionManagerLookup is specified
		// in Hibernate configuration, it will contain a TransactionManager reference.
		TransactionManager jtaTm = getJtaTransactionManager(sessionFactory, session);
		if (jtaTm != null) {
			try {
				Transaction jtaTx = jtaTm.getTransaction();
				if (jtaTx != null) {
					int jtaStatus = jtaTx.getStatus();
					if (jtaStatus == Status.STATUS_ACTIVE || jtaStatus == Status.STATUS_MARKED_ROLLBACK) {
						logger.debug("Registering JTA transaction synchronization for new Hibernate Session");
						SessionHolder holderToUse = sessionHolder;
						// Register JTA Transaction with existing SessionHolder.
						// Create a new SessionHolder if none existed before.
						if (holderToUse == null) {
							holderToUse = new SessionHolder(jtaTx, session);
						}
						else {
							holderToUse.addSession(jtaTx, session);
						}
						jtaTx.registerSynchronization(
								new SpringJtaSynchronizationAdapter(
										new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true),
										jtaTm));
						holderToUse.setSynchronizedWithTransaction(true);
						if (holderToUse != sessionHolder) {
							TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse);
						}
					}
				}
			}
			catch (Throwable ex) {
				throw new DataAccessResourceFailureException(
						"Could not register synchronization with JTA TransactionManager", ex);
			}
		}
	}

  getNewSession

  获取一个新的Session,尽可能共享当前线程绑定的SessionHolder的任何一个Session的数据库连接Connection,这种Connection依赖生命周期的管理在hibernate3.x api中有详细介绍
/**
	 * Get a new Hibernate Session from the given SessionFactory.
	 * Will return a new Session even if there already is a pre-bound
	 * Session for the given SessionFactory.
	 * <p>Within a transaction, this method will create a new Session
	 * that shares the transaction's JDBC Connection. More specifically,
	 * it will use the same JDBC Connection as the pre-bound Hibernate Session.
	 * @param sessionFactory Hibernate SessionFactory to create the session with
	 * @param entityInterceptor Hibernate entity interceptor, or {@code null} if none
	 * @return the new Session
	 */
	public static Session getNewSession(SessionFactory sessionFactory, Interceptor entityInterceptor) {
		Assert.notNull(sessionFactory, "No SessionFactory specified");

		try {
			SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
			if (sessionHolder != null && !sessionHolder.isEmpty()) {
				if (entityInterceptor != null) {
					return sessionFactory.openSession(sessionHolder.getAnySession().connection(), entityInterceptor);
				}
				else {
					return sessionFactory.openSession(sessionHolder.getAnySession().connection());
				}
			}
			else {
				if (entityInterceptor != null) {
					return sessionFactory.openSession(entityInterceptor);
				}
				else {
					return sessionFactory.openSession();
				}
			}
		}
		catch (HibernateException ex) {
			throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
		}
	}


  isDeferredCloseActive,initDeferredClose,processDeferredClose,closeSessionOrRegisterDeferredClose
  这四个是关注可能的SessionFactory延迟关闭。isDeferredCloseActive判断SessionFactory是否标志位延迟关闭;initDeferredClose标志SessionFactory延迟关闭;processDeferredClose关闭SessionFactory管理的所有延迟的Session;closeSessionOrRegisterDeferredClose将可能的SessionFactory管理的Session延放在延迟Map中,否则直接关闭Session。Session的延迟关闭策略主要在OpenSessionInviewFilter/Interceptor和事务框架中实现。  
/**
	 * Determine whether deferred close is active for the current thread
	 * and the given SessionFactory.
	 * @param sessionFactory the Hibernate SessionFactory to check
	 * @return whether deferred close is active
	 */
	public static boolean isDeferredCloseActive(SessionFactory sessionFactory) {
		Assert.notNull(sessionFactory, "No SessionFactory specified");
		Map<SessionFactory, Set<Session>> holderMap = deferredCloseHolder.get();
		return (holderMap != null && holderMap.containsKey(sessionFactory));
	}

	/**
	 * Initialize deferred close for the current thread and the given SessionFactory.
	 * Sessions will not be actually closed on close calls then, but rather at a
	 * {@link #processDeferredClose} call at a finishing point (like request completion).
	 * <p>Used by {@link org.springframework.orm.hibernate3.support.OpenSessionInViewFilter}
	 * and {@link org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor}
	 * when not configured for a single session.
	 * @param sessionFactory the Hibernate SessionFactory to initialize deferred close for
	 * @see #processDeferredClose
	 * @see #releaseSession
	 * @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter#setSingleSession
	 * @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor#setSingleSession
	 */
	public static void initDeferredClose(SessionFactory sessionFactory) {
		Assert.notNull(sessionFactory, "No SessionFactory specified");
		logger.debug("Initializing deferred close of Hibernate Sessions");
		Map<SessionFactory, Set<Session>> holderMap = deferredCloseHolder.get();
		if (holderMap == null) {
			holderMap = new HashMap<SessionFactory, Set<Session>>();
			deferredCloseHolder.set(holderMap);
		}
		holderMap.put(sessionFactory, new LinkedHashSet<Session>(4));
	}

	/**
	 * Process all Hibernate Sessions that have been registered for deferred close
	 * for the given SessionFactory.
	 * @param sessionFactory the Hibernate SessionFactory to process deferred close for
	 * @see #initDeferredClose
	 * @see #releaseSession
	 */
	public static void processDeferredClose(SessionFactory sessionFactory) {
		Assert.notNull(sessionFactory, "No SessionFactory specified");
		Map<SessionFactory, Set<Session>> holderMap = deferredCloseHolder.get();
		if (holderMap == null || !holderMap.containsKey(sessionFactory)) {
			throw new IllegalStateException("Deferred close not active for SessionFactory [" + sessionFactory + "]");
		}
		logger.debug("Processing deferred close of Hibernate Sessions");
		Set<Session> sessions = holderMap.remove(sessionFactory);
		for (Session session : sessions) {
			closeSession(session);
		}
		if (holderMap.isEmpty()) {
			deferredCloseHolder.remove();
		}
	}

	/**
	 * Close the given Session, created via the given factory,
	 * if it is not managed externally (i.e. not bound to the thread).
	 * @param session the Hibernate Session to close (may be {@code null})
	 * @param sessionFactory Hibernate SessionFactory that the Session was created with
	 * (may be {@code null})
	 */
	public static void releaseSession(Session session, SessionFactory sessionFactory) {
		if (session == null) {
			return;
		}
		// Only close non-transactional Sessions.
		if (!isSessionTransactional(session, sessionFactory)) {
			closeSessionOrRegisterDeferredClose(session, sessionFactory);
		}
	}

	/**
	 * Close the given Session or register it for deferred close.
	 * @param session the Hibernate Session to close
	 * @param sessionFactory Hibernate SessionFactory that the Session was created with
	 * (may be {@code null})
	 * @see #initDeferredClose
	 * @see #processDeferredClose
	 */
	static void closeSessionOrRegisterDeferredClose(Session session, SessionFactory sessionFactory) {
		Map<SessionFactory, Set<Session>> holderMap = deferredCloseHolder.get();
		if (holderMap != null && sessionFactory != null && holderMap.containsKey(sessionFactory)) {
			logger.debug("Registering Hibernate Session for deferred close");
			// Switch Session to FlushMode.MANUAL for remaining lifetime.
			session.setFlushMode(FlushMode.MANUAL);
			Set<Session> sessions = holderMap.get(sessionFactory);
			sessions.add(session);
		}
		else {
			closeSession(session);
		}
	}
0
1
分享到:
评论

相关推荐

    Hibernate中的sessionFactory

    在Java的持久化框架Hibernate中,`SessionFactory`是核心组件之一,它扮演着数据库会话的工厂角色。SessionFactory是通过`Configuration`接口配置并初始化的,这个过程涉及到读取ORM映射文件,设置数据库连接参数等...

    SPRING API 2.0.CHM

    All Classes AbstractAdvisorAutoProxyCreator AbstractApplicationContext AbstractApplicationEventMulticaster AbstractAspectJAdvice AbstractAspectJAdvisorFactory AbstractAspectJAdvisorFactory....

    1、hibernate调用存储过程1

    因此,推荐使用`SessionFactoryUtils`的`getDataSource`方法,或者直接利用`SessionFactory`的`getConnectionProvider`方法获取`Connection`。 以下是一个示例,展示了如何使用`SessionFactory`获取`Connection`并...

    Spring+Hibernate.zip ppt

    此外,Spring 的 DAO 抽象层使得编写数据访问代码更加简洁,可以通过模板类(如 HibernateTemplate 或 SessionFactoryUtils)或基于 JPA 的 Repositories 实现。 综上所述,"Spring+Hibernate.zip"可能涵盖了如何...

    struts sping hibernate

    4. **Spring管理Hibernate**:Spring可以通过HibernateTemplate或SessionFactoryUtils来简化Hibernate的使用,提供事务管理。 5. **Spring MVC与Struts协作**:Spring MVC可以替代Struts的部分功能,两者可以通过...

    hibernate 延迟加载.docx

    【hibernate 延迟加载】 在Java的持久化框架Hibernate中,延迟加载(Lazy ...在使用`SessionFactoryUtils`等工具类管理`SessionFactory`和`Session`时,需注意其生命周期和关闭时机,以充分利用延迟加载的优势。

    ssh整合配置(struts2.2.1+ hibernate3.6+spring3.0.5)

    6. **整合Hibernate和Spring**:使用Spring的HibernateTemplate或SessionFactoryUtils进行数据访问,避免在Action或Service中直接操作Session。 7. **测试与运行**:编写测试用例,验证SSH整合是否成功,确保各层...

    SSH简单整合实例.rar

    4. **整合Spring和Hibernate**:Spring管理Hibernate的SessionFactory,通过Spring的`LocalSessionFactoryBean`创建SessionFactory,并使用`HibernateTemplate`或`SessionFactoryUtils`进行数据访问。 5. **整合...

    ssh项目整合

    5. **整合Spring和Hibernate**:在Spring配置文件中,配置SessionFactory Bean,并使用HibernateTemplate或SessionFactoryUtils进行数据库操作。 6. **整合Struts和Spring**:在Struts的Action中,通过Spring的依赖...

    spring事务精髓

    `SessionFactoryUtils.getSession`方法在获取Session时,会考虑当前是否存在有效的Session(例如在事务中),如果存在,则复用,否则创建新的Session。在事务开始时,Spring会创建一个Session并将其绑定到当前线程,...

    struts+spring+ibties+oracle整合

    7. **整合Hibernate和Spring**:使用Spring的HibernateTemplate或SessionFactoryUtils进行数据访问,避免手动管理Hibernate Session。 8. **数据库连接**:在Spring配置文件中配置DataSource,建立与Oracle数据库的...

    Struts1.3 + Hibernate3.3 + Spring3.0 Annotation整合

    5. **整合Hibernate和Spring**:通过Spring的HibernateTemplate或SessionFactoryUtils,可以在Service层中方便地操作数据库,避免了手动管理Session。 6. **测试**:创建Test1类进行单元测试或集成测试,确保各个...

    Spring整合hibernate

    7. **Spring整合Hibernate**:使用Spring的HibernateTemplate或SessionFactoryUtils等工具类,简化Hibernate的使用,避免手动关闭Session和Transaction。也可以选择使用Spring Data JPA,它提供了一种基于Repository...

    spring_hibernate_annotation的三种实现

    - **HibernateTemplate or SessionFactoryUtils**:提供操作Hibernate Session的便捷方法,如save, update, delete, get, load等。 4. **Spring Data JPA** - **Repository接口**:定义基本的CRUD操作,Spring ...

    java hibernate不同数据库之间的动态切换

    SessionFactoryUtils.bindSessionFactoryToThread(sessionFactory); } } ``` 4. **事务管理** - 在进行数据库操作时,确保使用`Transaction`对象进行事务控制,这将确保切换数据库时事务的一致性。 5. **使用...

    Struts1.2+Spring1.2+HIbernate3.1整合示例代码

    2. **Spring与Hibernate的整合**:Spring提供了HibernateTemplate或SessionFactoryUtils,使得开发者可以在不直接接触Session的情况下进行数据库操作,降低了代码的耦合度。Spring还负责管理Hibernate的...

    spring+Hibernate

    4. **HibernateTemplate或SessionFactoryUtils**:在较早版本的Spring中,常用`HibernateTemplate`作为DAO层的工具类,简化了与Hibernate Session的交互。而在现代版本中,推荐直接使用`SessionFactory`和`Session`...

Global site tag (gtag.js) - Google Analytics