Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA query timeout parameters ignored but @Transaction annotation works

I want JPA queries made by my Spring Boot application to a Postgres database to timeout after 5 seconds.

I have created this 20 seconds query to test timeouts:

@Query(value = "select count(*) from pg_sleep(20)", nativeQuery = true)
int slowQuery();

I've set the following properties in application.config:

spring.jpa.properties.javax.persistence.query.timeout=3000
javax.persistence.query.timeout=5000

But the query does not timeout after 3s or 5s (it still takes 20s to execute).

Strangely, if I annotate slowQuery with @Transactional(timeout = 10), it times out after 10s or so.

I would prefer not to annotate every query. I'm using JPA 2.0 and the Tomcat connection pool.

What magic is required to make the timeout work just by setting them in application properties file?

like image 583
ixe013 Avatar asked Dec 18 '18 05:12

ixe013


People also ask

What is hibernate timeout in JPA?

The timeout value is defined in milliseconds, so the JPQL query above will time out after 50 milliseconds unless the result set is being fetched prior to the timeout threshold. Hibernate also provides the org.hibernate.timeout query hint, which unlike its JPA counterpart, takes the timeout interval in seconds:

What is @query annotation in spring data JPA?

Overview Spring Data provides many ways to define a query that we can execute. One of these is the @Query annotation. In this tutorial, we'll demonstrate how to use the @Query annotation in Spring Data JPA to execute both JPQL and native SQL queries. We'll also show how to build a dynamic query when the @Query annotation is not enough.

Does @transactional annotation work on JDBC read timeout exception?

@Transactional annotation do not work on jdbc read timeout exception. Thanks for contributing an answer to Stack Overflow! Please be sure to answer the question. Provide details and share your research!

What is @transient annotation in JPA?

Introduction When persisting Java objects into database records using an Object-Relational Mapping (ORM) framework, we often want to ignore certain fields. If the framework is compliant with the Java Persistence API (JPA), we can add the @Transient annotation to these fields.


1 Answers

To make the timeout generic, in your JpaConfiguration, when you declare the PlatformTransactionManager Bean, you can set the default timeout of the transactions:

@Bean
public PlatformTransactionManager transactionManager() throws Exception {
    JpaTransactionManager txManager = new JpaTransactionManager();
    txManager.setEntityManagerFactory(entityManagerFactory().getObject());
    txManager.setDataSource(this.dataSource);
    txManager.setDefaultTimeout(10); //Put 10 seconds timeout
    return txManager;
}

PlatformTransactionManager inherits AbstractPlatformTransactionManager which contains that method:

    /**
     * Specify the default timeout that this transaction manager should apply
     * if there is no timeout specified at the transaction level, in seconds.
     * <p>Default is the underlying transaction infrastructure's default timeout,
     * e.g. typically 30 seconds in case of a JTA provider, indicated by the
     * {@code TransactionDefinition.TIMEOUT_DEFAULT} value.
     * @see org.springframework.transaction.TransactionDefinition#TIMEOUT_DEFAULT
     */
    public final void setDefaultTimeout(int defaultTimeout) {
        if (defaultTimeout < TransactionDefinition.TIMEOUT_DEFAULT) {
            throw new InvalidTimeoutException("Invalid default timeout", defaultTimeout);
        }
        this.defaultTimeout = defaultTimeout;
    }
like image 92
Francesc Recio Avatar answered Nov 09 '22 23:11

Francesc Recio