Search code examples
springhibernatespring-bootspring-data-jpaspring-transactions

Spring Data JPA Closed Connection


There is a function which inserts a record in the database with status "Running" at the start then do some long processing and at the end it updates the status to "Success" or "failed".

I am getting an error in the end while updating the status as processing took a long time ( 4 hrs to upload data to third-party app).

    java.sql.BatchUpdateException: ORA-02396: exceeded maximum idle time, please connect again
        SQL: update STATUS set status=?
        o.h.engine.jdbc.spi.SqlExceptionHelper   : ORA-02396: exceeded maximum idle time, please connect again
        ERROR [-,f292b6c9becb8716,f292b6c9becb8716,false] 13556 --- [nio-8080-exec-7] o.h.i.ExceptionMapperStandardImpl        : HHH000346: Error during managed flush [org.hibernate.exception.GenericJDBCException: could not execute batch]
WARN [-,f292b6c9becb8716,f292b6c9becb8716,false] 13556 --- [nio-8080-exec-7] com.zaxxer.hikari.pool.ProxyConnection   : HikariPool-2 - Connection oracle.jdbc.driver.T4CConnection@7fb2645b marked as broken because of SQLSTATE(08003), ErrorCode(17008)

java.sql.SQLRecoverableException: Closed Connection
    at oracle.jdbc.driver.PhysicalConnection.getAutoCommit(PhysicalConnection.java:1828)
    at oracle.jdbc.driver.PhysicalConnection.rollback(PhysicalConnection.java:1953)
    at com.zaxxer.hikari.pool.ProxyConnection.rollback(ProxyConnection.java:377)
    at com.zaxxer.hikari.pool.HikariProxyConnection.rollback(HikariProxyConnection.java)
    at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.rollback(AbstractLogicalConnectionImplementor.java:116)
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.rollback(JdbcResourceLocalTransactionCoordinatorImpl.java:251)
    at org.hibernate.engine.transaction.internal.TransactionImpl.rollback(TransactionImpl.java:100)

How I can handle this situation?

Below is my code snippet:

public void upload() {

            entity.setStatus("RUNNING");
            repository.save(entity);

            try {
                //Uploads data to thrid party;
                callingThridPartyApp();
                log.info("Upload successfull.");
                entity.setStatus("SUCCESS");
                repository.save(entity);
            } catch (Exception e) {
                log.error("Upload failed.", e);
                entity.setStatus("FAILED");
                repository.save(entity);
            } 

    }

Solution

  • I solved this issue by stating a new transaction at the end of the long process to update the status in database.

            @Transactional(propagation = Propagation.REQUIRES_NEW)
            public void updateStatus(Entity entity) {
    
                    log.info("Upload successfull.");
                    entity.setStatus("SUCCESS");
                    repository.save(entity);
    
                } catch (Exception e) {
                    log.error("Upload failed.", e);
                    entity.setStatus("FAILED");
                    repository.save(entity);
                } 
             }