2010-01-20 110 views
7

我正在用Hibernate对我的数据库做一些大的查询,而且有时候我会打超时。我想避免每个QueryCriteria手动设置超时。Hibernate:设置默认查询超时?

有没有我可以给我的AnnotationConfiguration的任何属性,它会为我运行的所有查询设置可接受的默认值?

如果不是,我如何设置Hibernate查询的默认超时值?

+0

您是否正在使用连接池。 – Bozho 2010-01-20 13:03:12

+0

是的,使用C3PO – malaverdiere 2010-01-22 09:43:37

回答

5

JPA 2定义javax.persistence.query.timeout提示指定以毫秒为单位的默认超时之前。 Hibernate 3.5(目前仍处于测试阶段)将支持这个提示。

参见http://opensource.atlassian.com/projects/hibernate/browse/HHH-4662

+0

我并不太兴奋构建测试版...看看网站,我没有看到预期的发布日期。你知道他们何时计划发布它吗? – malaverdiere 2010-01-21 06:20:13

+0

CR发布只有几个星期的时间,我认为3.5之后不久。在优先级列表中,JPA 2遵从性很高,因此不存在该问题属于该表的风险。 – Hardy 2010-01-21 14:00:29

+0

当查询处于死锁状态时,此超时正在处理这种情况? – Laszlo 2016-08-17 10:43:21

1

这里有几个方面:

  • 使用一个工厂或基类的方法来创建所有的查询和设置超时返回查询对象
  • 创建自己的org.hibernate.loader的版本之前。加载程序并在doQuery中设置超时值
  • 使用AOP,例如Spring,返回Session的代理;添加通知它封装了的createQuery方法和设置查询对象上的超时返回它
+0

我以为做了第一个选项,你首先想到的,但我认为“当然,Hibernate提供了一种方法来避免这种情况!“ 关于Loader,我并不太兴奋创建一个新的,但我认为我可以扩展'BasicLoader',事实是,我没有在该API中看到'doQuery':因此,我将不得不重写哪些方法?我猜'doList','getResultSet' ,'prepareQueryStatement'和'scroll'我是对吗? – malaverdiere 2010-01-21 06:16:42

+0

我可能是错的,但我不认为Hibernate允许你以这种方式挂载到加载器。我使用与Hibernate相同的包将hibernate加载器从源代码拷贝到我的项目中;因为我的类在类路径中处于Hibernate之前,所以我使用了它。唯一的缺点是每次升级Hibernate时都必须这样做,但是如果您可以在Queries之前到达PreparedStatement对象ery运行,你可以调用setQueryTimeout,所以prepareQueryStatement可能是你最好的选择。 – 2010-01-22 14:40:21

3

JDBC有这个机制命名查询超时,你可以调用java.sql.Statement中的对象的setQueryTime方法来启用此设置。

Hibernate无法以统一的方式做到这一点。

如果您的应用程序检索JDBC连接vi java.sql.DataSource,则可以轻松解决该问题。

我们可以创建一个DateSourceWrapper来代理Connnection,它为它创建的每个Statement创建setQueryTimeout。

示例代码很容易阅读,我使用了一些spring util类来帮助实现。

public class QueryTimeoutConfiguredDataSource extends DelegatingDataSource { 

private int queryTimeout; 

public QueryTimeoutConfiguredDataSource(DataSource dataSource) { 
    super(dataSource); 
} 

// override this method to proxy created connection 
@Override 
public Connection getConnection() throws SQLException { 
    return proxyWithQueryTimeout(super.getConnection()); 
} 

// override this method to proxy created connection 
@Override 
public Connection getConnection(String username, String password) throws SQLException { 
    return proxyWithQueryTimeout(super.getConnection(username, password)); 
} 

private Connection proxyWithQueryTimeout(final Connection connection) { 
    return proxy(connection, new InvocationHandler() { 
     //All the Statement instances are created here, we can do something 
     //If the return is instance of Statement object, we set query timeout to it 
     @Override 
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
      Object object = method.invoke(connection, args); 
      if (object instanceof Statement) { 
       ((Statement) object).setQueryTimeout(queryTimeout); 
      } 
      return object; 
     }); 
} 

private Connection proxy(Connection connection, InvocationHandler invocationHandler) { 
    return (Connection) Proxy.newProxyInstance(
      connection.getClass().getClassLoader(), 
      ClassUtils.getAllInterfaces(connection), 
      invocationHandler); 
} 

public void setQueryTimeout(int queryTimeout) { 
    this.queryTimeout = queryTimeout; 
} 

}

现在我们可以使用这个QueryTimeoutConfiguredDataSource为包装你的存在的DataSource设置查询超时为每个语句透明!

Spring配置文件:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
    <property name="dataSource"> 
     <bean class="com.stackoverflow.QueryTimeoutConfiguredDataSource"> 
      <constructor-arg ref="dataSource"/> 
      <property name="queryTimeout" value="1" /> 
     </bean> 
    </property> 
</bean> 
0

对于在查询级别设置全局超时值 - 添加下面的配置文件。

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> 
    <property name="dataSource" ref="dataSource"></property> 
    <property name="queryTimeout" value="60"></property> 
</bean> 

用于在事务(INSERT/UPDATE)级别设置全局超时值 - 将以下添加到配置文件。

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="myEmf" /> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="defaultTimeout" value="60" /> 
    <property name="jpaDialect"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> 
    </property> 
</bean> 
+0

当我做maven构建时,我得到一个错误,我指出在这里的查询 你能帮忙:http://stackoverflow.com/questions/41613160/default-query-timeout-is-causing-exception-in-集成测试 – Pavanraotk 2017-01-13 05:45:14