使用getCurrentSession()时获取“找不到当前线程的会话”exception
我使用的是Spring MVC 4.0.6和Hibernate 4.3.5。 我试图将值插入我的数据库表,但我收到此错误消息:
HTTP状态500 – 请求处理失败; 嵌套exception是org.hibernate.HibernateException:找不到当前线程的Session
目前我使用sessionFactory.getCurrentSession()
来保存我的数据,但是如果我使用getSessionFactory().openSession();
它完美地运作。 我听说我应该使用getCurrentSession
而不是getSessionFactory().openSession();
因为每次进行数据库查询时都会创建一个新会话。
你可以在下面看看我的代码并告诉我我做错了什么以及如何让sessionFactory.getCurrentSession()
工作?
GradeServiceImpl:
@Service @Transactional public class GradeServiceImpl implements GradeService { @Autowired private GradeDao gradeDao; @Override public void addGrade(Grade grade) { gradeDao.addGrade(grade); } }
GradeDaoImpl
@Repository @Transactional public class GradeDaoImpl implements GradeDao { @Autowired private SessionFactory sessionFactory; public SessionFactory getSessionFactory() { return sessionFactory; } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } @Override public void addGrade(Grade grade) { sessionFactory.getCurrentSession().save(grade); } }
servlet的context.xml中
<!-- classpath:hibernate.cfg.xml --> org.hibernate.dialect.MySQLDialect true create true
在web.xml
contextConfigLocation /WEB-INF/spring/root-context.xml org.springframework.web.context.ContextLoaderListener appServlet org.springframework.web.servlet.DispatcherServlet contextConfigLocation /WEB-INF/spring/appServlet/servlet-context.xml 1 appServlet /
更新 – 堆栈跟踪
例外
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.HibernateException: No Session found for current thread org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:973) org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863) javax.servlet.http.HttpServlet.service(HttpServlet.java:647) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
根本原因
org.hibernate.HibernateException: No Session found for current thread org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:106) org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014) com.spring.org.dao.GradeDaoImpl.addGrade(GradeDaoImpl.java:33) com.spring.org.service.GradeServiceImpl.addGrade(GradeServiceImpl.java:25) com.spring.org.GradeController.saveGrade(GradeController.java:32) sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) java.lang.reflect.Method.invoke(Unknown Source) org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215) org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132) org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749) org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689) org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961) org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863) javax.servlet.http.HttpServlet.service(HttpServlet.java:647) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837) javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
在你的hibernate属性中,添加这一行。
thread
所以你的hibernateProperties看起来像这样,
org.hibernate.dialect.MySQLDialect true create //add this thread true
你需要开一个交易。 所以这样做。
public void addGrade(Grade grade) { Session session = sessionFactory.getCurrentSession() Transaction tx = null; try{ tx = session.beginTransaction(); session.save(grade); tx.commit(); }catch (HibernateException e) { if (tx!=null) tx.rollback(); e.printStackTrace(); }finally { session.close(); } }
}
我有同样的问题。
我使用的是基于注释的配置,我已经配置了sessionfactory,datasource和事务管理器。 但是我没有在AppConfig类中给出@EnableTransactionManagement注释。
添加事务注释后,代码如下所示。
@Configuration @ComponentScan("com.bmp.*") @EnableWebMvc @PropertySource("classpath:${env}.properties") @EnableTransactionManagement public class AppConfig { ----- }
上面的注释解决了我的问题。
如果这可以解决您的问题,请进行投票,以便对其他人有所帮助。
您应该删除DAO实现上的@Transactional注释。 而是在您的Service方法中;
@Override @Transactional public void addGrade(Grade grade) { gradeDao.addGrade(grade); }
对于所有数据库操作,只有服务实现需要@Transactional。
这是最新发生的事情:
当你使用sessionFactory.getCurrentSession()
而不是sessionFactory.openSession()
hibernate将寻找绑定到应用程序上下文线程的会话实例(换句话说,单个会话实例将由hibernate管理,并在会话中调用getCurrentSession()时返回工厂)。
现在要配置绑定到应用程序上下文线程的会话,您必须在hibernate属性中指定它。 你可以通过向hibernateProperties
添加以下属性来实现:
thread
之所以sessionFactory.openSession()
没有hibernate属性的情况下正常工作是因为hibernate不会查找绑定到应用程序上下文的会话,每次在sessionFactory
上调用openSession()
时都需要创建一个新的会话实例。
希望这对你有所帮助。
正如Narmer所说,你将所有的数据库配置放在servlet-context.xml
,它应该放在root-context.xml
。 但问题的真正原因(或其症状)是您不使用事务代理,因为它可以在stacktrace中看到: GradeController.saveGrade
直接调用GradeServiceImpl.addGrade
,而GradeServiceImpl.addGrade
又直接调用GradeDaoImpl.addGrade
。
通常,您应该仅将@Transactional
注释放在服务层中,而不是放在dao层中(只有一个事务层)。 并且您应该validation您是否从控制器自动assembly服务
@Autowired private GradeService gradeService;
请尝试仅使用一个事务层,并说出stacktrace是否显示事务代理使用情况。
编辑:
您的配置中还有另一个问题:当spring需要正确处理@Transactional
注释时,您没有
标记。
尝试使用旧版本的弹簧…我使用弹簧3.2.8.RELEASE与hibernate 4.2.11.Final …