昨天发现的问题今天又看了一下,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,问题就出在这里。
?
?
?