2010-01-20 22 views
7

Estoy haciendo algunas grandes consultas en mi base de datos con Hibernate y a veces me salen los tiempos de espera. Me gustaría evitar configurar manualmente el tiempo de espera en cada Query o Criteria.Hibernar: ¿establecer tiempo de espera de consulta predeterminado?

¿Hay alguna propiedad que pueda darle a mi AnnotationConfiguration que establezca un valor predeterminado aceptable para todas las consultas que ejecuto?

En caso negativo, ¿cómo puedo establecer un valor de tiempo de espera predeterminado en las consultas de Hibernate?

+0

¿Está utilizando un grupo de conexión. – Bozho

+0

Sí, usando C3PO – malaverdiere

Respuesta

5

JPA 2 define el javax.persistence.query.timeout pista para especificar tiempo de espera predeterminado en milisegundos. Hibernate 3.5 (actualmente todavía en versión beta) apoyará esta sugerencia.

Ver también http://opensource.atlassian.com/projects/hibernate/browse/HHH-4662

+0

No estoy muy entusiasmado con la construcción de una versión beta ... Al echar un vistazo al sitio, no veo una fecha de lanzamiento esperada. ¿Sabes cuándo planean lanzarlo? – malaverdiere

+0

El lanzamiento de CR está a solo un par de semanas y creo que 3.5 seguirá poco después. El cumplimiento de JPA 2 ocupa un lugar destacado en la lista de prioridades, por lo que no existe riesgo de que el problema quede bajo la mesa. – Hardy

+0

¿Este tiempo de espera está funcionando en ese caso, cuando la consulta está en punto muerto? – Laszlo

1

Estas son algunas de las formas:

  • Uso de una fábrica o un método de la clase base para crear todas las consultas y establecer el tiempo de espera antes de devolver el objeto Query
  • crear su propia versión de org.hibernate.loader. Cargador y establecer el tiempo de espera en doQuery
  • Usar AOP, por ejemplo Spring, para devolver un proxy para la sesión; añadir consejos a ella que envuelve el método CreateQuery y establece el tiempo de espera del objeto de consulta antes de devolverlo
+0

Pensé en hacer la primera opción que diste al principio, pero pensé "¡seguramente, Hibernate ofrece una manera de evitar esto!" Acerca del cargador, no estoy muy entusiasmado con la idea de crear uno nuevo en su totalidad. Pero pensé que tal vez podía extender' BasicLoader'. El problema es que no veo 'doQuery' en esa API: https://www.hibernate.org/hib_docs/v3/api/org/hibernate/loader/Loader.html Entonces, ¿tendría que anular qué métodos? Supongo que 'doList',' getResultSet' , 'prepareQueryStatement' y' scroll'. ¿Estoy en lo correcto? – malaverdiere

+0

Podría estar equivocado, pero no creo que Hibernate te permita conectar el cargador de esa manera. Copié el cargador hibernate de la fuente en mi proyecto usando el mismo paquete que Hibernate. dado que mis clases están por delante de Hibernate en el classpath, el mío se usa. El único inconveniente es que tienes que hacer eso cada vez que actualizas Hibernate. Pero si puedes llegar al objeto PreparedStatement antes del qu Si ejecuta ery, puede llamar a setQueryTimeout, por lo que prepareQueryStatement podría ser su mejor opción. –

3

JDBC tiene este mecanismo llamado Tiempo de espera de consulta, puede llamar al método de objeto setQueryTime java.sql.Statement habilitar esta configuración.

Hibernate no puede hacer esto de forma unificada.

Si su aplicación recupera la conexión JDBC vi java.sql.DataSource, la pregunta se puede resolver fácilmente.

podemos crear un DateSourceWrapper para proxy Connnection que establece setQueryTimeout para cada instrucción que crea.

El código de ejemplo es fácil de leer, utilizo algunas clases de Spring Spring para ayudarlo.

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; 
} 

}

Ahora podemos utilizar este QueryTimeoutConfiguredDataSource a su envoltorio existe fuente de datos para establecer espera de consulta para cada declaración transparente! archivo de configuración

primavera:

<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

Para establecer los valores globales de tiempo de espera a nivel de consulta - Añadir el siguiente al archivo de configuración.

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

Para establecer los valores globales de tiempo de espera en la transacción (INSERT/UPDATE) Nivel - Añadir el siguiente al archivo de configuración.

<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

Recibo un error cuando hago una compilación, he señalado la consulta aquí Puede ayudar: http://stackoverflow.com/questions/41613160/default-query-timeout-is-causing-exception-in- examen de integración – Pavanraotk

Cuestiones relacionadas