Could not obtain transaction-synchronized Session for current thread
Posted 哆啦任意门
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Could not obtain transaction-synchronized Session for current thread相关的知识,希望对你有一定的参考价值。
今天运行程序时 报了 如下的错误。
Could not obtain transaction-synchronized Session for current thread
在Spring中使用Hibernate,如果我们配置了TransactionManager,那么我们就不应该调用SessionFactory的openSession()来获得Sessioin,因为这样获得的Session并没有被事务管理。我们应该使用getCurrentSession()
Spring 修改
在Spring中,如果我们在没有配置TransactionManager并且没有事先调用SessionFactory.openSession()的情况直接调用getCurrentSession(),那么程序将抛出“No Session found for current thread”异常。如果配置了TranactionManager并且通过@Transactional或者声明的方式配置的事务边界,那么Spring会在开始事务之前通过AOP的方式为当前线程创建Session,此时调用getCurrentSession()将得到正确结果。
可以由上面的看到首先在Spring 和Hibernate 整合时 ,如果我们没有配置TranscationManager,但是直接调用了getCurrentSession(),那么就出现了这个错误,所以我们现在首先要将TranscationManager 加入进来。
解决办法:
1. 在Spring中加入事务 即使这个只是个查询的事务,不过我们可以设置此为一个ReadOnly 事务
1) 将事务的标签加入对应的方法中
1 @Transactional(readOnly = true) 2 public int findBookPriceByIsbn(String isbn) { 3 String hql = "SELECT b.price FROM Book b WHERE b.isbn = ?"; 4 Query<Integer> query = getSession().createQuery(hql).setParameter(0, isbn); 5 return query.uniqueResult(); 6 }
2)在xml中配置事务
1 <bean id="transactionManager" 2 class="org.springframework.orm.hibernate5.HibernateTransactionManager"> 3 <property name="sessionFactory" ref="localSessionFactoryBean"></property> 4 </bean> 5 6 <tx:annotation-driven transaction-manager="transactionManager" />
Hibernate中修改:
其实我们也可以在Hibernate 中进行修改 , 当我们不需要Spring的时候
然而,产生以上异常的原因在于Spring提供了自己的CurrentSessionContext实现,如果我们不打算使用Spring,而是自己直接从hibernate.cfg.xml创建SessionFactory,并且为在hibernate.cfg.xml
中设置current_session_context_class为thread,也即使用了ThreadLocalSessionContext,那么我们在调用getCurrentSession()时,如果当前线程没有Session存在,则会创建一个绑定到当前线程。
我们可以看到 当我们不使用Spring的时候 其实也会出现这个错误,归根结底在于有没有开这个session
解决方案:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 5 <hibernate-configuration> 6 <session-factory> 7 <property name="hibernate.dialect">org.hibernate.dialect.mysql5InnoDBDialect</property> 8 <property name="hibernate.show_sql">true</property> 9 <property name="hibernate.format_sql">true</property> 10 <property name="hibernate.hbm2ddl.auto">update</property>
//添加新的属性 11 <property name="current_session_context_class">thread</property> 12 </session-factory> 13 </hibernate-configuration>
web.xml解决方案:
在项目中,利用SessionFactory.getCurrentSession()方法获取hibernate的会话,当在一个controller方法中多次使用访问数据库,会报出错误:Could not obtain transaction-synchronized Session for current thread
在这里应该用一下spring中的OpenSessionInViewFilter,否则,需要每次使用完成后关闭session,下一次使用才不会报错,但是又涉及到一个lazy loading的问题,关闭session之后就无法懒加载,所以使用OpenSessionInViewFilter是一个两全的选择
1 <filter> 2 <filter-name>SpringOpenSessionInViewFilter</filter-name> 3 <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> 4 </filter> 5 <filter-mapping> 6 <filter-name>SpringOpenSessionInViewFilter</filter-name> 7 <url-pattern>/*</url-pattern> 8 </filter-mapping>
参考资料:
1.SpringMVC4+Hibernate4运行报错Could not obtain transaction-synchronized Session for current thread
2. Hibernate4 No Session found for current thread原因
3. spring+hibernate Could not obtain transaction-synchronized Session for current thread
以上是关于Could not obtain transaction-synchronized Session for current thread的主要内容,如果未能解决你的问题,请参考以下文章
Could not obtain transaction-synchronized Session for current thread
Could not obtain transaction-synchronized Session for current thread
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thre
Could not obtain transaction-synchronized Session for current thread
Could not obtain connection metadata
Could not obtain connection to query metadata : Public Key Retrieval is not allowed