当前位置: 代码迷 >> 驱动开发 >> Spring4+Hibernate4+测试驱动开发时发现的有关问题:No session (下)
  详细解决方案

Spring4+Hibernate4+测试驱动开发时发现的有关问题:No session (下)

热度:192   发布时间:2016-04-28 10:17:47.0
Spring4+Hibernate4+测试驱动开发时发现的问题:No session (下)

昨天发现的问题今天又看了一下,Hibernate的SessionFactory接口的实现类是SessionFactoryImpl。它在创建Session时候的工作原理如下:

?

?

当调用SessionFactory.getCurrentSession的时候,它会调用CurrentSessionContext接口子类实例的currentSession()方法来获得Session,那CurrentSessionContext子类实例是怎么创建的呢?

SpringFactoryImpl会根据配置文件制定的"hibernate.current_session_context_class"这个配置项来决定实例化哪种CurrentSessionContext的子类实例。SessionFactoryImpl会通过先调用buildCurrentSessionContext()方法加载session管理的策略,然后生成对应策略的CurrentSessionContext子类实例以供SessionFactoryImpl使用。

?

以下是buildCurrentSessionContext()方法的代码:

private CurrentSessionContext buildCurrentSessionContext() {		String impl = properties.getProperty( Environment.CURRENT_SESSION_CONTEXT_CLASS );		// for backward-compatibility		if ( impl == null ) {			if ( canAccessTransactionManager() ) {				impl = "jta";			}			else {				return null;			}		}		if ( "jta".equals( impl ) ) {			if ( ! transactionFactory().compatibleWithJtaSynchronization() ) {				LOG.autoFlushWillNotWork();			}			return new JTASessionContext( this );		}		else if ( "thread".equals( impl ) ) {			return new ThreadLocalSessionContext( this );		}		else if ( "managed".equals( impl ) ) {			return new ManagedSessionContext( this );		}		else {			try {				Class implClass = serviceRegistry.getService( ClassLoaderService.class ).classForName( impl );				return ( CurrentSessionContext ) implClass						.getConstructor( new Class[] { SessionFactoryImplementor.class } )						.newInstance( this );			}			catch( Throwable t ) {				LOG.unableToConstructCurrentSessionContext( impl, t );				return null;			}		}	}

?在我上一篇博客提到,我没有设置任何hibernate.current_session_context_class的配置,这个时候为什么没报异常呢?通过Debug它的代码,发现Spring4在默认情况下会设org.springframework.orm.hibernate4.SpringSessionContext这个值作为hibernate.current_session_context_class属性的值,也就是说在默认情况下,SpringSessionContext作为Spring4-orm的Session生成策略类。

再看以下SpringSessionContext的currentSession()方法,代码如下:

public Session currentSession() throws HibernateException {		Object value = TransactionSynchronizationManager.getResource(this.sessionFactory);		if (value instanceof Session) {			return (Session) value;		}		else if (value instanceof SessionHolder) {			SessionHolder sessionHolder = (SessionHolder) value;			Session session = sessionHolder.getSession();			if (TransactionSynchronizationManager.isSynchronizationActive() &&					!sessionHolder.isSynchronizedWithTransaction()) {				TransactionSynchronizationManager.registerSynchronization(						new SpringSessionSynchronization(sessionHolder, this.sessionFactory));				sessionHolder.setSynchronizedWithTransaction(true);				// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session				// with FlushMode.MANUAL, which needs to allow flushing within the transaction.				FlushMode flushMode = session.getFlushMode();				if (flushMode.equals(FlushMode.MANUAL) &&						!TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {					session.setFlushMode(FlushMode.AUTO);					sessionHolder.setPreviousFlushMode(flushMode);				}			}			return session;		}		else if (this.jtaSessionContext != null) {			Session session = this.jtaSessionContext.currentSession();			if (TransactionSynchronizationManager.isSynchronizationActive()) {				TransactionSynchronizationManager.registerSynchronization(new SpringFlushSynchronization(session));			}			return session;		}		else {			throw new HibernateException("No Session found for current thread");		}	}

?如果我们没有配置事务,?

Object?value?=?TransactionSynchronizationManager.getResource(this.sessionFactory);????

这个值会是null,问题就出在这里。

?

?

?

  相关解决方案