コード例 #1
0
 /**
  * Method to return a string form of this object for convenience debug.
  *
  * @return The String form
  */
 public String toString() {
   return StringUtils.toJVMIDString(this)
       + " [conn="
       + StringUtils.toJVMIDString(conn)
       + ", commitOnRelease="
       + commitOnRelease
       + ", closeOnRelease="
       + closeOnRelease
       + ", closeOnTxnEnd="
       + closeAfterTransactionEnd()
       + "]";
 }
コード例 #2
0
 public String toString() {
   return "StateManager[pc="
       + StringUtils.toJVMIDString(getObject())
       + ", lifecycle="
       + myLC
       + "]";
 }
コード例 #3
0
  /**
   * 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;
  }
コード例 #4
0
 public String toString() {
   return "StmtState : stmt="
       + StringUtils.toJVMIDString(stmt)
       + " sql="
       + stmtText
       + " batch="
       + batchSize
       + " closeOnProcess="
       + closeStatementOnProcess;
 }
コード例 #5
0
  /**
   * Convenience method to retrieve field values from an L2 cached object if they are loaded in that
   * object. If the object is not in the L2 cache then just returns, and similarly if the required
   * fields aren't available.
   *
   * @param fieldNumbers Numbers of fields to load from the L2 cache
   * @return The fields that couldn't be loaded
   */
  protected int[] loadFieldsFromLevel2Cache(int[] fieldNumbers) {
    // Only continue if there are fields, and not being deleted/flushed etc
    if (fieldNumbers == null
        || fieldNumbers.length == 0
        || myEC.isFlushing()
        || myLC.isDeleted()
        || isDeleting()
        || getExecutionContext().getTransaction().isCommitting()) {
      return fieldNumbers;
    }
    // TODO Drop this check when we're confident that this doesn't affect some use-cases
    if (!myEC.getNucleusContext()
        .getConfiguration()
        .getBooleanProperty(PropertyNames.PROPERTY_CACHE_L2_LOADFIELDS, true)) {
      return fieldNumbers;
    }

    Level2Cache l2cache = myEC.getNucleusContext().getLevel2Cache();
    if (l2cache != null && myEC.getNucleusContext().isClassCacheable(cmd)) {
      CachedPC<T> cachedPC = l2cache.get(myID);
      if (cachedPC != null) {
        int[] cacheFieldsToLoad =
            ClassUtils.getFlagsSetTo(cachedPC.getLoadedFields(), fieldNumbers, true);
        if (cacheFieldsToLoad != null && cacheFieldsToLoad.length > 0) {
          if (NucleusLogger.CACHE.isDebugEnabled()) {
            NucleusLogger.CACHE.debug(
                Localiser.msg(
                    "026034",
                    StringUtils.toJVMIDString(getObject()),
                    myID,
                    StringUtils.intArrayToString(cacheFieldsToLoad)));
          }

          L2CacheRetrieveFieldManager l2RetFM = new L2CacheRetrieveFieldManager(this, cachedPC);
          this.replaceFields(cacheFieldsToLoad, l2RetFM);
          int[] fieldsNotLoaded = l2RetFM.getFieldsNotLoaded();
          if (fieldsNotLoaded != null) {
            for (int i = 0; i < fieldsNotLoaded.length; i++) {
              loadedFields[fieldsNotLoaded[i]] = false;
            }
          }
        }
      }
    }

    return ClassUtils.getFlagsSetTo(loadedFields, fieldNumbers, false);
  }
コード例 #6
0
  /**
   * Convenience method to update a Level2 cached version of this object if cacheable and has not
   * been modified during this transaction.
   *
   * @param fieldNumbers Numbers of fields to update in L2 cached object
   */
  protected void updateLevel2CacheForFields(int[] fieldNumbers) {
    String updateMode = (String) myEC.getProperty(PropertyNames.PROPERTY_CACHE_L2_UPDATE_MODE);
    if (updateMode != null && updateMode.equalsIgnoreCase("commit-only")) {
      return;
    }
    if (fieldNumbers == null || fieldNumbers.length == 0) {
      return;
    }

    Level2Cache l2cache = myEC.getNucleusContext().getLevel2Cache();
    if (l2cache != null
        && myEC.getNucleusContext().isClassCacheable(cmd)
        && !myEC.isObjectModifiedInTransaction(myID)) {
      CachedPC<T> cachedPC = l2cache.get(myID);
      if (cachedPC != null) {
        // This originally just updated the L2 cache for fields where the L2 cache didn't have a
        // value for that field, like this
        /*
        int[] cacheFieldsToLoad = ClassUtils.getFlagsSetTo(cachedPC.getLoadedFields(), fieldNumbers, false);
        if (cacheFieldsToLoad == null || cacheFieldsToLoad.length == 0)
        {
            return;
        }
        */
        int[] cacheFieldsToLoad = fieldNumbers;
        CachedPC copyCachedPC = cachedPC.getCopy();
        if (NucleusLogger.CACHE.isDebugEnabled()) {
          NucleusLogger.CACHE.debug(
              Localiser.msg(
                  "026033",
                  StringUtils.toJVMIDString(getObject()),
                  myID,
                  StringUtils.intArrayToString(cacheFieldsToLoad)));
        }

        provideFields(cacheFieldsToLoad, new L2CachePopulateFieldManager(this, copyCachedPC));

        // Replace the current L2 cached object with this one
        myEC.getNucleusContext().getLevel2Cache().put(getInternalObjectId(), copyCachedPC);
      }
    }
  }
コード例 #7
0
  /**
   * 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;
  }
コード例 #8
0
 /**
  * Convenience method to close a PreparedStatement. If the statement is currently being used as a
  * batch, will register it for closing when executing the batch
  *
  * @param conn The Connection
  * @param ps The PreparedStatement
  * @throws SQLException if an error occurs closing the statement
  */
 public void closeStatement(ManagedConnection conn, PreparedStatement ps) throws SQLException {
   ConnectionStatementState state = getConnectionStatementState(conn);
   if (state != null && state.stmt == ps) {
     // Statement to be closed is the current batch, so register it for closing when it gets
     // processed
     state.closeStatementOnProcess = true;
   } else {
     try {
       if (NucleusLogger.DATASTORE.isDebugEnabled()) {
         NucleusLogger.DATASTORE.debug(LOCALISER.msg("052110", StringUtils.toJVMIDString(ps)));
       }
       ps.close();
     } catch (SQLException sqle) {
       // workaround for DBCP bug: even though PreparedStatement.close()
       // is defined as having no effect if already closed, DBCP
       // will throw SQLException
       if (!sqle.getMessage().equals("Already closed")) {
         throw sqle;
       }
     }
   }
 }
コード例 #9
0
  /**
   * Convenience method to process the currently waiting statement for the passed Connection. Only
   * processes the statement if it is in processable state.
   *
   * @param conn The connection
   * @return The return codes from the statement batch
   * @throws SQLException if an error occurs processing the batch
   */
  protected int[] processConnectionStatement(ManagedConnection conn) throws SQLException {
    ConnectionStatementState state = getConnectionStatementState(conn);
    if (state == null || !state.processable) {
      return null;
    }

    long startTime = System.currentTimeMillis();
    if (NucleusLogger.DATASTORE_NATIVE.isDebugEnabled()) {
      if (state.stmt instanceof ParamLoggingPreparedStatement) {
        NucleusLogger.DATASTORE_NATIVE.debug(
            ((ParamLoggingPreparedStatement) state.stmt).getStatementWithParamsReplaced());
      } else {
        NucleusLogger.DATASTORE_NATIVE.debug(state.stmtText);
      }
    }

    int[] ind = state.stmt.executeBatch();
    state.stmt.clearBatch();

    if (NucleusLogger.DATASTORE.isDebugEnabled()) {
      NucleusLogger.DATASTORE.debug(
          LOCALISER.msg(
              "045001",
              "" + (System.currentTimeMillis() - startTime),
              StringUtils.intArrayToString(ind),
              StringUtils.toJVMIDString(state.stmt)));
    }

    // Remove the current connection statement
    removeConnectionStatementState(conn);

    // Close the statement if it is registered for closing after processing
    if (state.closeStatementOnProcess) {
      state.stmt.close();
    }

    return ind;
  }
コード例 #10
0
 public String getObjectAsPrintable() {
   return StringUtils.toJVMIDString(getObject());
 }
コード例 #11
0
  /**
   * 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};
  }
コード例 #12
0
  /**
   * 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;
  }