0

I am currently working with ejb3, Java 1.8, jboss and oracle project. I am having a issue with CallableStatement. I have a procedure that is called when a CSV file is processed. When the procedure it called for the first time most of the time it never ends. But when a reuse the procedure again it work perfectly. Could you please give me any advice how to deal with this situation?

cStmt = prepareCall("{call CPRPA_TPT_PRICE_CALC.tpt_data_import(?,?)}");


import java.sql.CallableStatement;
import java.sql.SQLException;
import java.sql.Connection;
import java.util.HashMap;

import javax.persistence.EntityManager;

import org.hibernate.Session;
import org.hibernate.engine.spi.SessionImplementor;


public abstract class ProcDao extends BaseDao {
  /** Callable statement cache */
  private HashMap<String, CallableStatement> callableStatementCache = null;
  /** Session */
  private Session session = null;

  /**
   * Constructor
   *
   * @param entityManager Entity manager
   */
  public ProcDao(EntityManager entityManager) {
    super(entityManager);
  }

  /**
   * Creates a callable statement and stores it in the callable statement cache.
   *
   * @param sqlString SQL statement
   * @return Native query
   * @throws SQLException Database error
   */
  @SuppressWarnings({"deprecation"})
  protected CallableStatement prepareCall(String sqlString) throws SQLException {
    if (callableStatementCache == null) {
      callableStatementCache = new HashMap<String, CallableStatement>();
    }
    CallableStatement callableStatement = callableStatementCache.get(sqlString);
    if (callableStatement == null) {
      if (session == null) {
        session = (Session) entityManager.getDelegate();        
      } 
      
      SessionImplementor sessionImplementor = (SessionImplementor)session;
      Connection conn = sessionImplementor.connection();
      callableStatement = conn.prepareCall(sqlString);
      callableStatementCache.put(sqlString, callableStatement);
    }
    return callableStatement;
  }
    

  /** Closes the cached callable statements and connections. */
  public void close() {
    if (callableStatementCache != null && callableStatementCache.size() > 0) {
      for (CallableStatement callableStatement : callableStatementCache.values()) {
        try {
          Connection connection = callableStatement.getConnection();
          callableStatement.close();
          connection.close();
        } catch (Throwable ex) {
          ex.printStackTrace();
        }
      }
      callableStatementCache.clear();
    }
    if (session != null) {
      if(session.isOpen()){ 
          session.disconnect();
      }
      session = null;
      
    }
  }
}


import java.sql.CallableStatement;
import java.sql.SQLException;
import javax.persistence.EntityManager;

public class ImportPriceLevelProcedureManagerDao extends ProcDao {
    
    /**
     * Constructor
     * 
     * @param entityManager {@link EntityManager}
     */
    public ImportPriceLevelProcedureManagerDao(EntityManager entityManager) {
        super(entityManager);
    }

    public void invokeImportPriceFromTempTableProcedure(int sessionId, String userID) throws DataException {
        CallableStatement cStmt = null;     
        try {
            cStmt = prepareCall("{call CPRPA_TPT_PRICE_CALC.tpt_data_import(?,?)}");
            cStmt.setInt(1, sessionId);
            cStmt.setString(2, userID);
            cStmt.execute();
        } catch (SQLException e) {
            throw new DatabaseException("Database exception occured!" + e);
        } catch (RuntimeException e) {
            throwDataException(e);
        } finally {
              try {
                  cStmt.close();
                } catch (SQLException e) {
                  throw new DatabaseException("Unable to release the Callable Statement");
                }
              }
        
    }

@Stateful(name = "xxxx/ImportPriceLevelProcedureManager")
public class ImportPriceLevelProcedureManagerBean extends ProcManagerBean<ImportPriceLevelProcedureManagerDao>  implements ImportPriceLevelProcedureManager, ImportPriceLevelProcedureManagerLocal {

    /** Entity-Manager */
    @PersistenceContext(type = PersistenceContextType.TRANSACTION, unitName = "xxxx")
    private EntityManager entityManager;

    /**
     * Set entity manager for testing purpose
     * 
     * @param entityManager {@link EntityManager}
     */
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
    /** {@inheritDoc} */
    @Override
    public void invokeImportPriceFromTempTableProcedure(int sessionId, String userID) throws DataException {
        getDao().invokeImportPriceFromTempTableProcedure(sessionId, userID);
    }
    
  • You do not include the code for the stored procedure. How are we expected to solve the problem if we cannot see it? – MT0 Oct 12 '21 at 21:44
  • Is the database session active? What is it waiting on? My wild guess is that the database session is active and it is blocked waiting on a lock that is held by some other session. And the process of retrying/ restarting either happens after the lock holder has released the lock or it somehow causes the lock holder's transaction to be rolled back. – Justin Cave Oct 12 '21 at 22:23
  • MT0 The stored procedure is woking fine I test from db side. Also i didn't upload because is 400 line. Justin Cave I think this can be the issue. The session can be active after executing one day before, but i am not sure .THe problem here is that the code is in production and it have many different active session and this part of the code at least it is executed one time a day and it process at least 30 000 record for day and I was wondering what is the best way to handle this part? – Dorian Haxhiaj Oct 18 '21 at 18:01

0 Answers0