/** * Convenience method to create a new PreparedStatement for a query. * * @param conn The Connection to use for the statement * @param stmtText Statement text * @param resultSetType Type of result set * @param resultSetConcurrency Concurrency for the result set * @return The PreparedStatement * @throws SQLException thrown if an error occurs creating the statement */ public PreparedStatement getStatementForQuery( ManagedConnection conn, String stmtText, String resultSetType, String resultSetConcurrency) throws SQLException { Connection c = (Connection) conn.getConnection(); if (supportsBatching) { // Check for a waiting batched statement that is ready for processing ConnectionStatementState state = getConnectionStatementState(conn); if (state != null && state.processable) { // Process the batch statement before returning our new query statement processConnectionStatement(conn); } } // Create a new PreparedStatement for this query PreparedStatement ps = null; if (resultSetType != null || resultSetConcurrency != null) { int rsTypeValue = ResultSet.TYPE_FORWARD_ONLY; if (resultSetType != null) { if (resultSetType.equals("scroll-sensitive")) { rsTypeValue = ResultSet.TYPE_SCROLL_SENSITIVE; } else if (resultSetType.equals("scroll-insensitive")) { rsTypeValue = ResultSet.TYPE_SCROLL_INSENSITIVE; } } int rsConcurrencyValue = ResultSet.CONCUR_READ_ONLY; if (resultSetConcurrency != null && resultSetConcurrency.equals("updateable")) { rsConcurrencyValue = ResultSet.CONCUR_UPDATABLE; } ps = c.prepareStatement(stmtText, rsTypeValue, rsConcurrencyValue); ps .clearBatch(); // In case using statement caching and given one with batched statements // left hanging (C3P0) } else { ps = c.prepareStatement(stmtText); ps .clearBatch(); // In case using statement caching and given one with batched statements // left hanging (C3P0) } if (queryTimeout > 0) { // Apply any query timeout ps.setQueryTimeout(queryTimeout / 1000); // queryTimeout is in milliseconds } if (NucleusLogger.DATASTORE.isDebugEnabled()) { NucleusLogger.DATASTORE.debug(LOCALISER.msg("052110", StringUtils.toJVMIDString(ps))); } if (!jdbcStatements) { // Wrap with our parameter logger ps = new ParamLoggingPreparedStatement(ps, stmtText); ((ParamLoggingPreparedStatement) ps).setParamsInAngleBrackets(paramValuesInBrackets); } return ps; }
/** * Method to execute a PreparedStatement query, and return the ResultSet. Prints logging * information about timings. * * @param conn The connection (required since the one on PreparedStatement is not always the same * so we can't use it) * @param stmt The statement text * @param ps The Prepared Statement * @return The ResultSet from the query * @throws SQLException Thrown if an error occurs */ public ResultSet executeStatementQuery( ExecutionContext ec, ManagedConnection conn, String stmt, PreparedStatement ps) throws SQLException { if (supportsBatching) { ConnectionStatementState state = getConnectionStatementState(conn); if (state != null) { if (state.processable) { // Current batch statement is processable now so lets just process it before processing // our query processConnectionStatement(conn); } else { // Current wait statement is not processable now so leave it in wait state if (NucleusLogger.DATASTORE_RETRIEVE.isDebugEnabled()) { NucleusLogger.DATASTORE_RETRIEVE.debug(LOCALISER.msg("052106", state.stmtText, stmt)); } } } } // Execute this query long startTime = System.currentTimeMillis(); if (NucleusLogger.DATASTORE_NATIVE.isDebugEnabled()) { if (ps instanceof ParamLoggingPreparedStatement) { NucleusLogger.DATASTORE_NATIVE.debug( ((ParamLoggingPreparedStatement) ps).getStatementWithParamsReplaced()); } else { NucleusLogger.DATASTORE_NATIVE.debug(stmt); } } ResultSet rs = ps.executeQuery(); if (ec != null && ec.getStatistics() != null) { // Add to statistics ec.getStatistics().incrementNumReads(); } ps.clearBatch(); if (NucleusLogger.DATASTORE_RETRIEVE.isDebugEnabled()) { NucleusLogger.DATASTORE_RETRIEVE.debug( LOCALISER.msg("045000", (System.currentTimeMillis() - startTime))); } return rs; }
/** * Method to execute a PreparedStatement (using PreparedStatement.execute()). Prints logging * information about timings. * * @param ec Execution Context * @param conn The connection (required since the one on PreparedStatement is not always the same * so we can't use it) * @param stmt The statement text * @param ps The Prepared Statement * @return The numer of rows affected (as per PreparedStatement.execute) * @throws SQLException Thrown if an error occurs */ public boolean executeStatement( ExecutionContext ec, ManagedConnection conn, String stmt, PreparedStatement ps) throws SQLException { if (supportsBatching) { // Check for a waiting batched statement that is ready for processing ConnectionStatementState state = getConnectionStatementState(conn); if (state != null && state.processable) { // Process the batch statement before returning our new query statement processConnectionStatement(conn); } } // Process the normal execute statement long startTime = System.currentTimeMillis(); if (NucleusLogger.DATASTORE_NATIVE.isDebugEnabled()) { if (ps instanceof ParamLoggingPreparedStatement) { NucleusLogger.DATASTORE_NATIVE.debug( ((ParamLoggingPreparedStatement) ps).getStatementWithParamsReplaced()); } else { NucleusLogger.DATASTORE_NATIVE.debug(stmt); } } boolean flag = ps.execute(); if (ec != null && ec.getStatistics() != null) { // Add to statistics ec.getStatistics().incrementNumWrites(); } ps.clearBatch(); if (NucleusLogger.DATASTORE_PERSIST.isDebugEnabled()) { NucleusLogger.DATASTORE_PERSIST.debug( LOCALISER.msg( "045002", "" + (System.currentTimeMillis() - startTime), StringUtils.toJVMIDString(ps))); } return flag; }
/** * Convenience method to process any batched statement for the specified connection. Typically * called when flush() or commit() are called. * * @param conn The connection * @throws SQLException Thrown if an error occurs on processing of the batch */ public void processStatementsForConnection(ManagedConnection conn) throws SQLException { if (!supportsBatching || getConnectionStatementState(conn) == null) { return; } processConnectionStatement(conn); }
/** * Method to execute a PreparedStatement update. Prints logging information about timings. * * @param conn The connection (required since the one on PreparedStatement is not always the same * so we cant use it) * @param stmt The statement text * @param ps The Prepared Statement * @param processNow Whether to process this statement now (only applies if is batched) * @return The numer of rows affected (as per PreparedStatement.executeUpdate) * @throws SQLException Thrown if an error occurs */ public int[] executeStatementUpdate( ExecutionContext ec, ManagedConnection conn, String stmt, PreparedStatement ps, boolean processNow) throws SQLException { ConnectionStatementState state = getConnectionStatementState(conn); if (state != null) { if (state.stmt == ps) { // Mark as processable if (NucleusLogger.DATASTORE_PERSIST.isDebugEnabled()) { NucleusLogger.DATASTORE_PERSIST.debug( LOCALISER.msg("052104", state.stmtText, "" + state.batchSize)); } state.processable = true; state.stmt.addBatch(); if (processNow) { // Process the batch now state.closeStatementOnProcess = false; // user method has requested execution so they can close it themselves now return processConnectionStatement(conn); } else { // Leave processing til later return null; } } else { // There is a waiting batch yet it is a different statement, so process that one now since // we need // our statement executing processConnectionStatement(conn); } } // Process the normal update statement long startTime = System.currentTimeMillis(); if (NucleusLogger.DATASTORE_NATIVE.isDebugEnabled()) { if (ps instanceof ParamLoggingPreparedStatement) { NucleusLogger.DATASTORE_NATIVE.debug( ((ParamLoggingPreparedStatement) ps).getStatementWithParamsReplaced()); } else { NucleusLogger.DATASTORE_NATIVE.debug(stmt); } } int ind = ps.executeUpdate(); if (ec != null && ec.getStatistics() != null) { // Add to statistics ec.getStatistics().incrementNumWrites(); } ps.clearBatch(); if (NucleusLogger.DATASTORE_PERSIST.isDebugEnabled()) { NucleusLogger.DATASTORE_PERSIST.debug( LOCALISER.msg( "045001", "" + (System.currentTimeMillis() - startTime), "" + ind, StringUtils.toJVMIDString(ps))); } return new int[] {ind}; }
/** * Convenience method to create a new PreparedStatement for an update. * * @param conn The Connection to use for the statement * @param stmtText Statement text * @param batchable Whether this statement is batchable. Whether we will process the statement * before any other statement * @param getGeneratedKeysFlag whether to request getGeneratedKeys for this statement * @return The PreparedStatement * @throws SQLException thrown if an error occurs creating the statement */ public PreparedStatement getStatementForUpdate( ManagedConnection conn, String stmtText, boolean batchable, boolean getGeneratedKeysFlag) throws SQLException { Connection c = (Connection) conn.getConnection(); if (supportsBatching) { ConnectionStatementState state = getConnectionStatementState(conn); if (state != null) { if (state.processable) { // We have a batchable statement in the queue that could be processed now if necessary if (!batchable) { // This new statement isnt batchable so process the existing one before returning our // new statement processConnectionStatement(conn); } else { // Check if we could batch onto this existing statement if (state.stmtText.equals(stmtText)) { // We can batch onto this statement if (maxBatchSize == -1 || state.batchSize < maxBatchSize) { state.batchSize++; state.processable = false; // Have to wait til we process this part til processable again if (NucleusLogger.DATASTORE_PERSIST.isDebugEnabled()) { NucleusLogger.DATASTORE_PERSIST.debug( LOCALISER.msg("052100", stmtText, "" + state.batchSize)); } return state.stmt; } else { // Reached max batch size so process it now and start again for this one if (NucleusLogger.DATASTORE_PERSIST.isDebugEnabled()) { NucleusLogger.DATASTORE_PERSIST.debug(LOCALISER.msg("052101", state.stmtText)); } processConnectionStatement(conn); } } else { // We cant batch using the current batch statement so process it first and return our // new one processConnectionStatement(conn); } } } else { if (batchable) { // The current statement is being batched so we cant batch this since cant process the // current statement now if (NucleusLogger.DATASTORE_PERSIST.isDebugEnabled()) { NucleusLogger.DATASTORE_PERSIST.debug( LOCALISER.msg("052102", state.stmtText, stmtText)); } batchable = false; } } } } PreparedStatement ps = (getGeneratedKeysFlag ? c.prepareStatement(stmtText, Statement.RETURN_GENERATED_KEYS) : c.prepareStatement(stmtText)); ps .clearBatch(); // In case using statement caching and given one with batched statements left // hanging (C3P0) if (!jdbcStatements) { // Wrap with our parameter logger ps = new ParamLoggingPreparedStatement(ps, stmtText); ((ParamLoggingPreparedStatement) ps).setParamsInAngleBrackets(paramValuesInBrackets); } if (NucleusLogger.DATASTORE.isDebugEnabled()) { NucleusLogger.DATASTORE.debug(LOCALISER.msg("052109", ps, StringUtils.toJVMIDString(c))); } if (batchable && supportsBatching) { // This statement is batchable so save it as the current batchable if (NucleusLogger.DATASTORE_PERSIST.isDebugEnabled()) { NucleusLogger.DATASTORE_PERSIST.debug(LOCALISER.msg("052103", stmtText)); } ConnectionStatementState state = new ConnectionStatementState(); state.stmt = ps; state.stmtText = stmtText; state.batchSize = 1; setConnectionStatementState(conn, state); } return ps; }