首页 > 解决方案 > Spring,Interceptors,一些 ExtJs 和控制台上的 HibernateException 与 IntelliJ

问题描述

奇怪的世界……让我试试:

我有以下 mavenized 设置:
- Springboot (1.5.5.RELEASE)
- Hibernate (5.0.9.Final;我知道有更新的变体,但我坚持我现在拥有的)
- ExtJs (6.0.0) - IntelliJ (2017.3)

我确实部分遇到了休眠异常:

2018-11-20_15:04:58.007 [http-nio-8081-exec-7] [ERROR] o.a.c.c.C.[.[.[/].[dispatcherServlet]:181 - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.hibernate.HibernateException: 
Could not obtain transaction-synchronized Session for current thread] with root cause  
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
    at org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:133)
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:697)
    ...

这不会发生在所有线程上!来自 ExtJs 的请求部分通过,部分不通过。但是他们不会在网络服务器端打开交易吗?

我确实有一个拦截器;以及一个 web 拦截器实现org.springframework.web.servlet.HandlerInterceptor 在拦截器的preHandle方法中,我确实调用了一个服务,以检查用户是否已登录并进行一些权限管理处理。

被调用的@Autowired服务失败。我认为访问@Autowired服务方法的事实会处理会话/事务处理。

好吧,这是我的项目手动创建并使用 java-8(java 8 sdk;不是 9,不是 10,不是 11)命令运行的场景,例如来自控制台:

mvn clean package -DskipTests && java -jar target/MyBuild.jar application-local.properties

我刚刚观察到登录由浏览器到后端的三个请求组成。这三个都由后端在单独的线程中处理。

在 IntelliJ 中运行项目时,一切正常。好的,IntelliJ 很可能不会jar应用程序并构建自己的启动命令。
但这确实让我失去了节奏,因为我们确实通过手动构建项目的部署/CI管道处理代码。
这就是它失败的地方:-(

修正:
我改变了一切以使用 JPA 而不是 Hibernate 运行(它仍然在后台休眠)。就像'M. Deinum 建议。
现在,问题依然存在。
我稍微提取了两件事。在我的拦截器中,我确实有一些记录调用,它们向 EntityManager 询问休眠会话(entityManager.unwrap( Session.class ))。
这就是现在的地步。所以似乎在preHandle(...)我的拦截器上有时没有当前会话处于活动状态。我说的是“有时”,因为在拦截器工作时会调用它。

现在异常如下:

java.lang.IllegalStateException: No transactional EntityManager available
  at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:272)
  at com.sun.proxy.$Proxy117.unwrap(Unknown Source)
  at com.mypackage.dataaccess.DataAccessImpl.getCurrentSession(DataAccessImpl.java:89)
  at com.mypackage.dataaccess.DataAccessImpl.queryByHQL(DataAccessImpl.java:382)

标签: javadatabasespringhibernateinterceptor

解决方案


好的。我最终注意到所有 Spring Web 控制器都有一个@Transactional(其中给出了 DB 使用情况。)
这行得通。

据我了解,只要通过spring的@Autowire机制调用方法/拥有对象,将@Transactional注释放在哪里都没有关系。 如果我想在事务行为下运行某些东西,我会在最接近的范围内用它进行注释。 这就是我决定在哪里放置@Transactional

最后它确实有效,但我对解决方案不满意。如果有人可以澄清行为和/或我的理解,欢迎告诉我:-)


推荐阅读