我在http请求上使用spring DeferredResult。 控制器接收到一些信息,进行一两次查询,然后返回DeferredResult。
为简单起见,我在DeferredResult上设置了一个超时时间,然后等待它。
final RandomObj randomObj = someDAO.getSomething(someParameters);
final CustomResponse response = new CustomResponse();
response.setError("need_password");
return new DeferredResult<CustomResponse>(10L, response);
但是由于某种原因,超时到期后返回的超时后,Hibernate Session并未关闭。
在c3p0中,可以选择终止长时间未返回的连接并调试问题,在DeferredResult情况下,我总是在一段时间后得到此结果:
jul 16, 2019 10:42:26 AM com.mchange.v2.resourcepool.BasicResourcePool removeResource
INFO: A checked-out resource is overdue, and will be destroyed: com.mchange.v2.c3p0.impl.NewPooledConnection@13b130de
jul 16, 2019 10:42:26 AM com.mchange.v2.resourcepool.BasicResourcePool removeResource
INFO: Logging the stack trace by which the overdue resource was checked-out.
java.lang.Exception: DEBUG STACK TRACE: Overdue resource check-out stack trace.
我通过在Session.close()方法上放置一些断点来确认会话未关闭。
在其他端点中,一切正常,请求到来,会话打开,查询,会话关闭,请求完成。
EDIT1:
Seens spring-orm不会针对此类异步事件自动关闭会话:
EDIT2:
DAO代码: (只是将实体名称更改为Foo,其余相同)
@Repository
public class FooDAOImpl extends CustomHibernateDaoSupport {
public Foo getByEmailAndAccountId(final String email, final Integer accountId, final Integer masterCompanyId) {
final List<Foo> list = (List<Foo>) getHibernateTemplate().findByNamedQueryAndNamedParam("Foo.getByEmailAndAccountId",
new String[] { "email", "accountId", "masterCompanyId" },
new Object[] { email, accountId, masterCompanyId });
}
}
EDIT3:
我认为我的问题是: Here已注册3个拦截器,您上面所说的AsyncRequestInterceptor是第二个。 执行超时触发器this代码后, 它首先触发this拦截器,此后,由于存在超时结果,因此它是assigned。 当迭代结束并且第二个拦截器(AsyncRequestInterceptor)将运行时,setOrExpired的结果(由于超时结果)为true,这会中断拦截器循环的执行。 因此,AsyncRequestInterceptor不会被标记为here,并且不会关闭会话 那是预期的行为?