2010-01-20 4 views
7

Я делаю несколько больших запросов в моей базе данных с Hibernate, и иногда я получаю таймауты. Я хотел бы избежать установки таймаута вручную на каждые Query или Criteria.Hibernate: установить тайм-аут запроса по умолчанию?

Есть ли какое-либо имущество, которое я могу предоставить моему AnnotationConfiguration, который установил бы приемлемый по умолчанию для всех запросов, которые я запускаю?

Если нет, как установить значение тайм-аута по умолчанию для Hibernate-запросов?

+0

Вы используете пул соединений. – Bozho

+0

Yup, используя C3PO – malaverdiere

ответ

5

JPA 2 определяет javax.persistence.query.timeout подсказки указать тайм-аут по умолчанию в миллисекундах. Hibernate 3.5 (в настоящее время все еще в бета-версии) будет поддерживать этот намек.

Смотрите также http://opensource.atlassian.com/projects/hibernate/browse/HHH-4662

+0

Я не слишком волнуюсь о создании бета-версии ... Взглянув на сайт, я не вижу ожидаемой даты выхода. Знаете ли вы, когда они планируют выпустить его? – malaverdiere

+0

Выпуск CR только на пару недель, и я думаю, что 3.5 последует вскоре. Согласование JPA 2 высоко в списке приоритетов, поэтому нет риска, что проблема будет подпадать под таблицу. – Hardy

+0

Этот тайм-аут работает в этом случае, когда запрос находится в тупике? – Laszlo

1

Вот несколько способов:

  • Используйте завод или метод базового класса для создания всех запросов и установить тайм-аут до возвращения объекта Query
  • Создать собственную версию org.hibernate.loader. Loader и установить тайм-аут в doQuery
  • Использовать AOP, например Spring, чтобы вернуть прокси для сеанса; добавить совет к нему, что оборачивает метод CreateQuery и устанавливает тайм-аут на объекте запроса до возвращения его
+0

Я думал о том, чтобы сделать первый вариант, который вы дали сначала, но я подумал: «Конечно, Hibernate предлагает способ избежать этого!« О загрузчике, я не слишком волнуюсь о создании нового в полном объеме. Но я подумал, что, возможно, я могу расширить« BasicLoader ». Дело в том, что я не вижу« doQuery »в этом API: https://www.hibernate.org/hib_docs/v3/api/org/hibernate/loader/Loader.html Итак, мне нужно было бы переопределить, какие методы? Я предполагаю 'doList',' getResultSet' , 'prepareQueryStatement' и' scroll'. Я прав? – malaverdiere

+0

Я мог ошибаться, но я не думаю, что Hibernate позволяет вам подключиться к загрузчику таким образом. Я скопировал загрузчик спящего режима из исходного кода в свой проект, используя тот же пакет, что и Hibernate , так как мои классы опережают Hibernate в пути к классам, мой использует. Единственный недостаток - это сделать это каждый раз, когда вы обновляете Hibernate. Но если вы можете добраться до объекта PreparedStatement до того, как qu ery, вы можете вызвать setQueryTimeout, поэтому prepareQueryStatement может быть вашим лучшим выбором. –

3

JDBC имеет этот механизм с именем запрос истек, вы можете вызвать метод setQueryTime объекта java.sql.Statement, чтобы включить этот параметр.

Hibernate не может сделать это унифицированным способом.

Если ваше приложение восстанавливает соединение JDBC vi java.sql.DataSource, вопрос может быть легко разрешен.

мы можем создать DateSourceWrapper для соединения с прокси-сервером, которые выполняют setQueryTimeout для каждого созданного ею оператора.

Пример кода легко читается, я использую некоторые классы весны, чтобы помочь этому.

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 build, я указал на запрос здесь Можете ли вы помочь: http://stackoverflow.com/questions/41613160/default-query-timeout-is-causing-exception-in- интеграция испытаний – Pavanraotk

Смежные вопросы