【问题标题】:How to cancel a running SQL query?如何取消正在运行的 SQL 查询?
【发布时间】:2015-11-26 06:23:22
【问题描述】:

我知道statement.cancel()可以用来取消一个正在运行的SQL查询,但我想知道的是,我将如何在另一个线程中获取这个语句对象。

用例:

  • 我请求启动一个运行语句的线程。
  • 然后从一个单独的请求(另一个线程)我可能想取消这个线程。

如何在这个新请求中获得调用cancel方法的语句。

在某些情况下,我会运行多个语句。

附加信息,它是一个web应用程序,使用spring框架、hibernate和JPA。现在在 UI 中有 2 个按钮,按钮 1 将触发 SQL 查询,按钮 2 必须取消该查询

我提到了this 示例,但它使用同一个线程来调用新线程,我不能这样做。

这是查询的开始方式:

    Query query = mEntityManager.createNativeQuery(globalQuery.toString());
    List<Object[]> results = query.getResultList();

编辑:

  1. 我能想到的一种方法是跟踪所有正在运行的语句,然后找到必须取消 SQL 语句的语句。

【问题讨论】:

  • 为什么不先说这个“SQL 查询”是从哪里调用的呢?
  • 所以我有 2 个客户端请求,第一个将启动查询,第二个应该取消它
  • 附加信息,它是一个web应用程序,使用spring框架,hibernate和JPA。现在在 UI 中有 2 个按钮,按钮 1 将触发 SQL 查询,而按钮 2 必须取消该查询。
  • 问题中更新了。
  • 设置查询提示“javax.persistence.query.timeout”,它应该超时。 JPA 不提供取消查询的机制(与 JDO 不同)。否则,如果您的提供商允许诸如取消之类的操作,您必须依赖供应商的详细信息

标签: java sql hibernate jpa


【解决方案1】:

有两种不同的课程可以帮助您:

如果您想在来自同一用户的两个请求之间交换类似语句的对象,无论这些请求是并行运行还是一个接一个地运行,您通常将它们存储在HttpSessionHttpServletRequest 中。

并且可以使用Hibernate的Session取消当前查询:

public void startLongRunningStatement() {
  EntityManager entityManager = ...

  // Aquire session
  Session hibernateSession = ((HibernateEntityManager) em.getDelegate()).getSession();

  // Store the HibernateSession in the HttpSession
  HttpSession httpSession = servletRequest.getSession()
  httpSession.setAttribute("hibernateSession", hibernateSession);

  try {
    // Run your query  
    Query query = mEntityManager.createNativeQuery(globalQuery.toString());
    List<?> results = query.getResultList();

  } finally {
    // Clear the session object, if it is still ours
    if (httpSession.getAttribute("hibernateSession") == hibernateSession) {
      httpSession.removeAttribute("hibernateSession");
    }
  }
}

public void cancel() {
  // Get the Hibernate session from the HTTP session
  HttpSession httpSession = servletRequest.getSession()
  Session hibernateSession = (Session) httpSession.getAttribute("hibernateSession");
  if (hibernateSession != null) {
    // Cancel the previous query
    hibernateSession.cancelQuery();
  }

}

【讨论】:

  • 你测试过这个吗?我试图以类似的方式实现,不同之处在于使用全局映射来存储与请求对应的会话对象。但我还没有完全测试过。所以我想知道这是否有效?
  • 是的,我用过不止一次。正如我所说,HttpSession 是跨请求存储数据的常用方法。您的全局请求映射有一个问题,您需要找到当前用户的上一个请求 - 如果您有匿名用户,这并不容易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-11
  • 1970-01-01
  • 2011-04-27
  • 2017-09-19
  • 1970-01-01
  • 2017-10-12
相关资源
最近更新 更多