我的问题隐藏在课堂上,有两种方法。
@Repository
@Transactional(isolation = Isolation.READ_COMMITTED)
public class RetentionController {
@Autowired
private SessionFactory sessionFactory;
...
@Transactional(readOnly = true)
public BaseResource getResource(String pPath)throws ResourceNotFoundException{
...
Criteria critDirExists = sessionFactory.getCurrentSession().createCriteria(Directory.class);
critDirExists.add(Restrictions.eq(PATH, pPath));
Directory dir = (Directory) critDirExists.uniqueResult();
...processing results...
}
@Transactional(readOnly = false)
public void addDirectory(String pPath) {
modelValidator.validateDirectoryURI(pPath);
//check if such exists
Criteria critExists = sessionFactory.getCurrentSession().createCriteria(Directory.class);
critExists.add(Restrictions.eq("path", pPath));
...
}
...
}
正确注入SessionFactory - 第一个方法正常执行。问题是: addDirectory在“Criteria critExists = sessionFactory.getCurrentSession()。createCriteria(Directory.class);”中抛出“没有Hibernate会话绑定到线程”,在“getResource()”方法之后调用它。
日志(我添加标记以查看方法的开始和结束位置:GET RESOURCE:START / END,ADD DIRECTORY:START / END):
DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'transactionManager'
DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] - Creating new transaction with name [com.asg.tciclientadapters.webdav.dal.RetentionController.getResource]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ''
DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] - Opened new Session [org.hibernate.impl.SessionImpl@1be3bb2] for Hibernate transaction
DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] - Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@1be3bb2]
DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Setting JDBC Connection [jdbc:sqlserver://******\****:****;selectMethod=direct;lastUpdateCount=true;, UserName=*********, Microsoft SQL Server 2005 JDBC Driver] read-only
DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] - Exposing Hibernate transaction as JDBC transaction [jdbc:sqlserver://******\****:****;selectMethod=direct;lastUpdateCount=true;, UserName=*********, Microsoft SQL Server 2005 JDBC Driver]
TRACE [org.springframework.transaction.support.TransactionSynchronizationManager] - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@13b8f62] for key [org.apache.commons.dbcp.BasicDataSource@115512] to thread [http-9080-1]
TRACE [org.springframework.transaction.support.TransactionSynchronizationManager] - Bound value [org.springframework.orm.hibernate3.SessionHolder@299629] for key [org.hibernate.impl.SessionFactoryImpl@1429498] to thread [http-9080-1]
TRACE [org.springframework.transaction.support.TransactionSynchronizationManager] - Initializing transaction synchronization
TRACE [org.springframework.transaction.interceptor.TransactionInterceptor] - Getting transaction for [com.asg.tciclientadapters.webdav.dal.RetentionController.getResource]
DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'com.asg.tciclientadapters.webdav.aspect.TraceLog#0'
DEBUG [com.asg.tciclientadapters.webdav.dal.RetentionController] - ---GET RESOURCE: START
TRACE [org.springframework.transaction.support.TransactionSynchronizationManager] - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@299629] for key [org.hibernate.impl.SessionFactoryImpl@1429498] bound to thread [http-9080-1]
DEBUG [com.asg.tciclientadapters.webdav.dal.RetentionController] - Getting ILM object: /CADPWebDAV
DEBUG [com.asg.tciclientadapters.webdav.dal.RetentionController] - RequestType is MKCOL
DEBUG [com.asg.tciclientadapters.webdav.dal.RetentionController] - EmbryoResource was created.
TRACE [org.springframework.transaction.support.TransactionSynchronizationManager] - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@299629] for key [org.hibernate.impl.SessionFactoryImpl@1429498] bound to thread [http-9080-1]
DEBUG [com.asg.tciclientadapters.webdav.dal.RetentionController] - ---GET RESOURCE: END
TRACE [com.asg.tciclientadapters.webdav.aspect.TraceLog] - RetentionController.getResource(..) Executed at: 78 ms
TRACE [com.asg.tciclientadapters.webdav.aspect.TraceLog] - Method Argument [1]: com.asg.tciclientadapters.webdav.servlet.CADPRequest@10241ae
TRACE [com.asg.tciclientadapters.webdav.aspect.TraceLog] - Method Argument [2]: com.asg.tciclientadapters.webdav.tci.TCIWrapper@1ca203
TRACE [org.springframework.transaction.interceptor.TransactionInterceptor] - Completing transaction for [com.asg.tciclientadapters.webdav.dal.RetentionController.getResource]
TRACE [org.springframework.orm.hibernate3.HibernateTransactionManager] - Triggering beforeCommit synchronization
TRACE [org.springframework.orm.hibernate3.HibernateTransactionManager] - Triggering beforeCompletion synchronization
DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] - Initiating transaction commit
DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] - Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@1be3bb2]
TRACE [org.springframework.orm.hibernate3.HibernateTransactionManager] - Triggering afterCommit synchronization
TRACE [org.springframework.orm.hibernate3.HibernateTransactionManager] - Triggering afterCompletion synchronization
TRACE [org.springframework.transaction.support.TransactionSynchronizationManager] - Clearing transaction synchronization
TRACE [org.springframework.transaction.support.TransactionSynchronizationManager] - Removed value [org.springframework.orm.hibernate3.SessionHolder@299629] for key [org.hibernate.impl.SessionFactoryImpl@1429498] from thread [http-9080-1]
TRACE [org.springframework.transaction.support.TransactionSynchronizationManager] - Removed value [org.springframework.jdbc.datasource.ConnectionHolder@13b8f62] for key [org.apache.commons.dbcp.BasicDataSource@115512] from thread [http-9080-1]
DEBUG [org.springframework.orm.hibernate3.HibernateTransactionManager] - Closing Hibernate Session [org.hibernate.impl.SessionImpl@1be3bb2] after transaction
DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Closing Hibernate Session
DEBUG [com.asg.tciclientadapters.webdav.dal.RetentionController] - ---ADD DIRECTORY: START
DEBUG [com.asg.tciclientadapters.webdav.dal.RetentionController] - Validation: OK
DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Opening Hibernate Session
DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Closing Hibernate Session
ERROR [com.asg.tciclientadapters.webdav.servlet.CADPServlet] - org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
Spring配置xml文件:
<context:property-placeholder location="classpath:spring.properties"/>
<context:annotation-config/>
<tx:annotation-driven/>
<aop:aspectj-autoproxy/>
<context:mbean-export/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
p:dataSource-ref="dataSource" p:mappingResources="CADPWebDAV_hbm.xml">
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
<prop key="hibernate.cache.use_structured_entries">true</prop>
</props>
</property>
<property name="eventListeners">
<map>
<entry key="merge">
<bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>
</entry>
</map>
</property>
</bean>'
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
p:sessionFactory-ref="sessionFactory"/>
以下是异常的StackTrace:
[com.asg.tciclientadapters.webdav.servlet.CADPServlet] - org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
[com.asg.tciclientadapters.webdav.servlet.CADPServlet] - org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
[com.asg.tciclientadapters.webdav.servlet.CADPServlet] - org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:687)
[com.asg.tciclientadapters.webdav.servlet.CADPServlet] - com.asg.tciclientadapters.webdav.dal.RetentionController.addDirectory(RetentionController.java:189)
...
答案 0 :(得分:2)
解决方案是 - 添加到web.xml:
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
此异常消失后。
答案 1 :(得分:0)
我认为您需要将addDirectory方法的@Transactional设置更改为以下内容:
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
基于我对Spring / Hibernate中事务管理过程如何工作的理解,您当前的设置告诉hibernate您将以只读方式执行所有内容,因此当您尝试以非只读方式执行时它爆炸了。我在http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#tx-propagation
找到了相关的支持文档我假设如果你在getResource之前调用你的addDirectory方法,那么你的代码就可以了。
答案 2 :(得分:0)
如果Hibernate的版本在类属性中没有完全对齐,就会发生这种情况。
transactionManager类org.springframework.orm.hibernate X 必须与SessionFactory类org.springframework.orm.hibernate X 版本匹配,这也需要得到您在maven依赖中使用的版本。