/*
(non-Javadoc)

@see com.ibm.ws.objectManager.ManagedObject#preDelete(com.ibm.ws.objectManager.Transaction)
427565
public synchronized void preDelete(Transaction transaction)
                    throws ObjectManagerException
    {
        final String methodName = "preDelete";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass,
                        methodName,
                        new Object[] { transaction });

        // The tree must be empty, apart from Entries this transaction will delete.
        Entry entry = null;
        if (root != null)
            entry = (Entry) AbstractTreeMap.minimum(getRoot());
        while (entry != null) {
            if (entry.willBeDeleted(transaction)) {
                entry = (Entry) successor(entry);
            } else {
                if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                    trace.exit(this, cclass,
                               methodName,
                               "via CollentionNotEmptyException"
                                               + "size=" + size + "(long)"
                                               + " entry.state=" + entry.state + "(int) " + Entry.stateNames[entry.state]
                                               + "\n entry.getTransactionLock=" + entry.getTransactionLock() + "(TransactionLock)"
                                    );

                throw new CollectionNotEmptyException(this, size, transaction);

            } // if (  entry.willBeDeleted...
        } // while (entry != null).

        super.preDelete(transaction); // Also takes a lock.
        // Visibility is now restricted to our transaction only.

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName);
    }
369736
public void delete(Collection collection) {
        pm.currentTransaction().begin();
        pm.deletePersistentAll(collection);
        pm.currentTransaction().commit();
    }
1218188
@Override
	public synchronized void delete(int contextId, int type, String data) throws DatabaseException {
    	SqlPreparedStatementWrapper psDeleteData = null;
    	try {
        	psDeleteData = DbSQL.getSingleton().getPreparedStatement("context.ps.delete");
			psDeleteData.getPs().setInt(1, contextId);
			psDeleteData.getPs().setInt(2, type);
			psDeleteData.getPs().setString(3, data);
			psDeleteData.getPs().executeUpdate();
		} catch (SQLException e) {
			throw new DatabaseException(e);
		} finally {
			DbSQL.getSingleton().releasePreparedStatement(psDeleteData);
		}
    }
731638
@SuppressWarnings("unchecked")
	@Override
	public <E> int delete(final Class<? extends E> entityType, final Object... keys) {
		@SuppressWarnings("rawtypes")
		EntityHandler handler = this.getEntityHandler();
		if (!handler.getEntityType().isAssignableFrom(entityType)) {
			throw new IllegalArgumentException("Entity type not supported");
		}

		try {
			TableMetadata metadata = handler.getMetadata(this.transactionManager, entityType);
			TableMetadata.Column keyColumn = null;
			List<? extends TableMetadata.Column> keyColumns = metadata.getKeyColumns();
			if (keyColumns.size() == 1) {
				keyColumn = keyColumns.get(0);
			} else if (keyColumns.isEmpty()) {
				keyColumn = metadata.getColumns().get(0);
			} else {
				throw new IllegalArgumentException("Entity has multiple keys");
			}
			return delete(entityType).in(keyColumn.getCamelColumnName(), keys).count();
		} catch (SQLException e) {
			throw new EntitySqlRuntimeException(SqlKind.DELETE, e);
		}
	}
931650
private MapEntryUpdateResult<K, byte[]> removeIf(long index, K key, Predicate<MapEntryValue> predicate) {
    MapEntryValue value = entries().get(key);

    // If the value does not exist or doesn't match the predicate, return a PRECONDITION_FAILED error.
    if (valueIsNull(value) || !predicate.test(value)) {
      return new MapEntryUpdateResult<>(MapEntryUpdateResult.Status.PRECONDITION_FAILED, index, key, null);
    }

    // If the key has been locked by a transaction, return a WRITE_LOCK error.
    if (preparedKeys.contains(key)) {
      return new MapEntryUpdateResult<>(MapEntryUpdateResult.Status.WRITE_LOCK, index, key, null);
    }

    // If no transactions are active, remove the key. Otherwise, replace it with a tombstone.
    if (activeTransactions.isEmpty()) {
      entries().remove(key);
    } else {
      entries().put(key, new MapEntryValue(MapEntryValue.Type.TOMBSTONE, index, null, 0, 0));
    }

    // Cancel the timer if one is scheduled.
    cancelTtl(value);

    Versioned<byte[]> result = toVersioned(value);
    publish(new AtomicMapEvent<>(AtomicMapEvent.Type.REMOVE, key, null, result));
    return new MapEntryUpdateResult<>(MapEntryUpdateResult.Status.OK, index, key, result);
  }
658306
@Override
    public void afterCompletion(TransactionCommon transaction, boolean committed)
    {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.entry(tc, "afterCompletion", new Object[] { transaction, Boolean.valueOf(committed) });

        synchronized (this)
        {
            // If the connection is already closed this transaction
            // will have been removed.
            if (!_closed)
            {
                synchronized (_ownedTransactions)
                {
                    // Remove the transaction from the connections list
                    _ownedTransactions.remove(transaction);
                }
            }
        }

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled())
            SibTr.exit(tc, "afterCompletion");
    }
557326
private boolean cleanLockedObjects(ITransaction transaction,
            LockedObject lo, boolean temporary) {

        if (lo._children == null) {
            if (lo._owner == null) {
                if (temporary) {
                    lo.removeTempLockedObject();
                } else {
                    lo.removeLockedObject();
                }

                return true;
            } else {
                return false;
            }
        } else {
            boolean canDelete = true;
            int limit = lo._children.length;
            for (int i = 0; i < limit; i++) {
                if (!cleanLockedObjects(transaction, lo._children[i], temporary)) {
                    canDelete = false;
                } else {

                    // because the deleting shifts the array
                    i--;
                    limit--;
                }
            }
            if (canDelete) {
                if (lo._owner == null) {
                    if (temporary) {
                        lo.removeTempLockedObject();
                    } else {
                        lo.removeLockedObject();
                    }
                    return true;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
    }
1170934
void preCommit(Transaction transaction)
                    throws ObjectManagerException
    {
        throw new InvalidStateException(this, InternalTransaction.stateTerminated, InternalTransaction.stateNames[InternalTransaction.stateTerminated]);
    }
1258054
final public void delete() {
		Transaction t = new Transaction();
		try {
			delete(t);
			t.setSuccessful(true);
		} finally {
			t.finish();
		}
	}
761610
public synchronized void preDelete(Transaction transaction)
                    throws ObjectManagerException
    {
        final String methodName = "preDelete";
        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.entry(this, cclass, methodName, new Object[] { transaction });

        // TODO Remove this fix, we should not need it now we do not split checkpoint sets.
        // Defect 326031
        // We only need to do this check once so at recovery time we
        // can rely on it having been done when the transaction first 
        // ran.
        // TODO: Can we avoid this check by grouping transaction work into a single checkpoint?
        // TODO: Re tested this on 18/6/07 and the failure still occurs even though we now write
        // TODO: complete transactions in a checkpoint. Here is a scenarion that might cause this,
        // TODO: however the actual test ( performance) does the delete for the entry and list as two
        //       separate serial tracactions!
        // 
        //   Application Thread          Checkpoint Helper      LogRecords   
        //  
        //   Delete Entry                                       Delete Entry 
        //   Delete List                                        Delete List
        //                               SetRequiresCheckpoint
        // 
        //                               Checkpoint Start       Checkpoint Start. 
        //                                                      Checkpoint Entry(Deleted)
        //                                                      Checkpoint List(Deleted)
        //
        //   Commit                                             Commit
        //   Delete Entry/List from Store
        //                               Flush ObjectStore             
        //                               Checkpoint End         Checkpoint End.  
        // 
        //   
        //   Crash 
        // 
        //   Recover List in Deleted state, 
        //   Entry not yet recovered in deleted state.

        if (transaction.getObjectManagerStateState() != ObjectManagerState.stateReplayingLog) {
            // The list must be empty, apart from links this transaction will delete.
            Token nextToken = head;
            while (nextToken != null) {
                Link nextLink = (Link) nextToken.getManagedObject();
                if (nextLink.willBeDeleted(transaction))
                    nextToken = nextLink.next;
                else {
                    if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
                        trace.exit(this, cclass,
                                   methodName,
                                   "via CollentionNotEmptyException"
                                                   + "size=" + size + "(long)"
                                                   + " nextLink.state=" + nextLink.state + "(int) " + Link.stateNames[nextLink.state]
                                                   + "\n nextLink.getTransactionLock()=" + nextLink.getTransactionLock() + "(transactionLock)"
                                        );

                    throw new CollectionNotEmptyException(this, size, transaction);
                    //System.out.println("LinkedList.preDelete nextLink.state ="+nextLink.state+" "+Link.stateNames[nextLink.state]
                    //                  +"\n nextLink.getTransactionLock()="+nextLink.getTransactionLock() 
                    //                  );
                    //break;
                } // if (  nextLink.state == Link.stateToBeDeleted...
            } // while (nextToken != null).
        } // if not recovering...

        super.preDelete(transaction); // Also takes a lock.
        // Visibility is now restricted to our transaction only.

        if (Tracing.isAnyTracingEnabled() && trace.isEntryEnabled())
            trace.exit(this, cclass, methodName);
    }
737614
public void prepare(PersistentTransaction transaction) throws PersistenceException, SevereMessageStoreException
    {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "prepare", "Transaction="+transaction);

        // Defect 363755
        if (!_available)
        {
            MessageStoreUnavailableException msue = new MessageStoreUnavailableException("Operation not possible as MessageStore is unavailable!");
            if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(this, tc, "Operation not possible as MessageStore is unavailable!");
            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "prepare");
            throw msue;
        }

        //Get the task list from the transaction
        TaskList taskList = (TaskList) transaction.getWorkList();

        PersistentTranId       xid = transaction.getPersistentTranId();
        TransactionState tranState = transaction.getTransactionState();
        int          numberOfTasks = taskList.countLinks();

        boolean requiresSyncPersistence = false;

        // Defect 530772
        boolean requiresSpillPersistence = false;

        // Defect 298584
        // Batching context will only be created if we
        // have synchronous work to do.
        BatchingContext syncBatch = null;
        List             syncList = null;

        if (taskList.hasStoreAlways() || taskList.hasStoreEventually() || taskList.hasStoreMaybe())
        {
            // We have synchronous work to do so
            // we need to build up a list of tasks.
            Iterator iterator = taskList.iterator();
            while (iterator.hasNext())
            {
                Operation          task = (Operation) iterator.next();
                Persistable persistable = task.getPersistable();

                // Defect 451518
                if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Preparing Task: "+task);

                if (persistable != null && persistable.requiresPersistence())
                {
                    int     storageStrategy = persistable.getStorageStrategy();
                    TupleTypeEnum tupleType = persistable.getTupleType();

                    // Feature SIB0112i.ms.1
                    // We only need to persist our synchronous work at this point. If our
                    // transaction prepares successfully then at commit time we can make
                    // sure our STORE_MAYBE work is persisted.

                    // Defect 530772
                    // Are we a STORE_MAYBE Item? If so then we can be dispatched to the
                    // spill dispatcher. If not then we need to be persisted synchronously.
                    // This is to avoid adding complication to the spill dispatcher as it
                    // does not worry about the order in which things are persisted so an
                    // Item on a stream can be hardened to disk before the stream. This will
                    // not work in the filestore case.
                    if (tupleType != TupleTypeEnum.ITEM_STREAM &&
                        tupleType != TupleTypeEnum.REFERENCE_STREAM &&
                        storageStrategy == AbstractItem.STORE_MAYBE)
                    {
                        if (requiresSpillPersistence == false)
                        {
                            requiresSpillPersistence = true;
                        }
                    }
                    // If not we are synchronous.
                    else
                    {
                        // Defect 298584
                        // Only create our batching context once we know for sure
                        // that we have some synchronous work to do.
                        if (requiresSyncPersistence == false)
                        {
                            syncList  = new ArrayList(numberOfTasks);
                            syncBatch = new BatchingContextImpl(_objectManager, _permanentStore, transaction);
                            transaction.setBatchingContext(syncBatch);
                            requiresSyncPersistence = true;
                        }

                        //Associate the global tran id with the persistable
                        persistable.setPersistentTranId(xid);

                        task.persist(syncBatch, tranState);
                        syncList.add(persistable);
                    }
                }
            }
        }


        // Defect 530772
        // Check the health of the spill dispatcher to minimise the risk
        // of splitting a transaction.
        if (requiresSpillPersistence)
        {
            if (!_spillDispatcher.isHealthy())
            {
                // Defect 345250
                // The dispatcher is not currently accepting new work as it has
                // hit a problem. Details of the problem should have been output
                // to the logs by the dispatcher thread at the point where it
                // occurred.
                PersistenceException pe = new PersistenceException("SPILL_DISPATCHER_CANNOT_ACCEPT_WORK_SIMS1578");
                if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(this, tc, "The spill dispatcher cannot accept work!", pe);
                if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "prepare");
                throw pe;
            }
        }

        // Feature SIB0112i.ms.1
        // We only have to do some work in prepare if we have
        // synchronous work to add to the file store.
        if (requiresSyncPersistence)
        {
            try
            {
                // As this is a prepare we use the addIndoubtXid()
                // method to inform the batching context that we only
                // wish to prepare during this executeUpdate() call.
                syncBatch.addIndoubtXID(xid);

                // Submit the batch and trigger the prepare in the
                // object manager.
                syncBatch.executeBatch();

                // If we get to this point then the prepare was successful, so we need to
                // notify the cache layer
                Iterator iterator = syncList.iterator();
                while (iterator.hasNext())
                {
                    Tuple tuple = (Tuple)iterator.next();

                    // Both these methods need to be called to indicate to the cache
                    // that it can soften its in-memory reference to the persistable
                    tuple.persistableOperationBegun();
                    tuple.persistableOperationCompleted();
                }
            }
            catch (PersistenceException pe)
            {
                com.ibm.ws.ffdc.FFDCFilter.processException(pe, "com.ibm.ws.sib.msgstore.persistence.objectManager.PersistableMessageStoreImpl.prepare", "1:1615:1.81.1.6", this);
                if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(this, tc, "Exception caught preparing transaction in object store!", pe);
                if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "prepare");
                throw pe;
            }
        }

        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(this, tc, "prepare");
    }
72814
static void rollbackIfActive(Transaction transaction) {
    try {
      if (transaction != null && transaction.isActive()) {
        transaction.rollback();
      }
    } catch (DatastoreException exp) {
      throw new EntityManagerException(exp);
    }
  }
931311
public void removeTransaction(String txId) {
            if(this.transactionMap.remove(txId) != null) {
                    if(logger.isDebugEnabled()) {
                            logger.debug("Transaction "+txId+" removed from proxy.");
                    }
            }
            checkAndCleanProxy();
    }
767099
public void beforeCompletion()
    {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(tc, "beforeCompletion");

        if (_state != TransactionState.STATE_ACTIVE)
        {
            MessageStoreRuntimeException mre = new MessageStoreRuntimeException(nls.getFormattedMessage("TRAN_PROTOCOL_ERROR_SIMS1001", new Object[]{}, null));
            if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(tc, "Cannot complete Transaction. Transaction is complete or completing!", mre);
            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(tc, "beforeCompletion");
            throw mre;
        }

        for (int i = 0; i < _callbacks.size(); i++)
        {
            TransactionCallback callback = (TransactionCallback) _callbacks.get(i);
            callback.beforeCompletion(this);
        }

        // Do we have work to do?
        if (_workList != null)
        {
            try
            {
                _workList.preCommit(this);
            }
            catch (Throwable t)
            {
                FFDCFilter.processException(t, "com.ibm.ws.sib.msgstore.transactions.MSDelegatingLocalTransactionSynchronization.beforeCompletion", "1:103:1.4.1.1", this);

                // An error has occurred during preCommit
                // so we need to trigger a rollback of our
                // transaction and therefore our connection
                // by throwing a runtime exception.
                if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(tc, "Throwing exception in beforeCompletion to ensure rollback due to Exception in preCommit!", t);
                if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(tc, "beforeCompletion");
                throw new MessageStoreRuntimeException(nls.getFormattedMessage("COMPLETION_EXCEPTION_SIMS1002", new Object[] {t}, null), t);
            }
        }

        // Need to change the state after we have 
        // called the callbacks and preCommitted 
        // the workList as they may trigger
        // an addWork call to add work to the
        // transaction.
        _state = TransactionState.STATE_COMMITTING_1PC;

        try
        {
            // Do we have work to do?
            if (_workList != null)
            {
                // Call the persistence layer to trigger our
                // database work on the shared connection.
                _persistence.beforeCompletion(this);
            }
        }
        catch (PersistenceException pe)
        {
            FFDCFilter.processException(pe, "com.ibm.ws.sib.msgstore.transactions.MSDelegatingLocalTransactionSynchronization.beforeCompletion", "1:134:1.4.1.1", this);
            // An error has occurred during the persistence
            // phase so we need to trigger a rollback of our
            // transaction and therefore our connection by
            // throwing a runtime exception.
            if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(tc, "Rollback-only set on transaction due to PersistenceException in beforeCompletion!", pe);
            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(tc, "beforeCompletion");
            throw new MessageStoreRuntimeException(nls.getFormattedMessage("COMPLETION_EXCEPTION_SIMS1002", new Object[] {pe}, null), pe);
        }
        catch (SevereMessageStoreException smse)
        {
            FFDCFilter.processException(smse, "com.ibm.ws.sib.msgstore.transactions.MSDelegatingLocalTransactionSynchronization.beforeCompletion", "1:145:1.4.1.1", this);
            // An error has occurred during the persistence
            // phase so we need to trigger a rollback of our
            // transaction and therefore our connection by
            // throwing a runtime exception.
            if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) SibTr.event(tc, "Rollback-only set on transaction due to PersistenceException in beforeCompletion!", smse);
            if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(tc, "beforeCompletion");
            throw new MessageStoreRuntimeException(nls.getFormattedMessage("COMPLETION_EXCEPTION_SIMS1002", new Object[] {smse}, null), smse);
        }
        
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(tc, "beforeCompletion");
    }
618922
public void removeOngoingTransaction(Transaction transaction) {
		boolean removed = false;
		if(this.ongoingTransactions != null) {
			removed = this.ongoingTransactions.remove(transaction);
		}

//		if(sessionCreatingTransactionRequest != null && sessionCreatingTransactionRequest.getMessage() != null && JainSipUtils.DIALOG_CREATING_METHODS.contains(sessionCreatingTransactionRequest.getMethod())) {
//			sessionCreatingTransactionRequest = null;
//		}

		if (proxy != null) {
		    proxy.removeTransaction(transaction.getBranchId());
		}

		if(logger.isDebugEnabled()) {
			logger.debug("transaction "+ transaction +" has been removed from sip session's ongoingTransactions ? " + removed );
		}

		updateReadyToInvalidate(transaction);
		// nullify the sessionCreatingTransactionRequest only after updateReadyToInvalidate as it is used for error response checking

		final String branchId = transaction.getBranchId();
		if(sessionCreatingTransactionRequest != null &&
				 branchId != null) {

			// https://github.com/RestComm/sip-servlets/issues/101 fix for NPE happening due to concurrent behavior cleaning the transaction
			final Transaction sessionCreatingTransactionRequestTransaction = sessionCreatingTransactionRequest.getTransaction();
			String sessionCreatingTransactionRequestTransactionBranchId = null;
			if(sessionCreatingTransactionRequestTransaction != null) {
				sessionCreatingTransactionRequestTransactionBranchId = sessionCreatingTransactionRequestTransaction.getBranchId();
			}
			final String sessionCreatingTransactionRequestMethod = sessionCreatingTransactionRequest.getMethod();

			if(sessionCreatingTransactionRequestTransaction != null &&
					branchId.equals(sessionCreatingTransactionRequestTransactionBranchId)) {

				if(logger.isDebugEnabled()) {
					logger.debug("Session " + key + ": cleaning up "+ sessionCreatingTransactionRequest
							+ " since transaction " + transaction + " with branch id " + branchId
							+ " is the same as sessionCreatingRequestTransaction " +  sessionCreatingTransactionRequestTransaction
							+ " with branch id " + sessionCreatingTransactionRequestTransactionBranchId
							+ " and method " + sessionCreatingTransactionRequestMethod);
				}
				sessionCreatingTransactionRequest.cleanUp();
				// https://telestax.atlassian.net/browse/MSS-153 improve performance by cleaning the request for dialog based requests
				// or proxy case or dialog creating methods
				if(sessionCreatingDialog != null || proxy != null || JainSipUtils.DIALOG_CREATING_METHODS.contains(sessionCreatingTransactionRequestMethod)) {
					if(logger.isDebugEnabled()) {
						logger.debug("removeOngoingTransaction - sessionCreatingTransactionRequest=" + sessionCreatingTransactionRequest);
					}
					if(logger.isDebugEnabled() && sessionCreatingTransactionRequest != null) {
						logger.debug("nullifying  sessionCreatingTransactionRequest" + sessionCreatingTransactionRequest
								+ " from Session " + key);
					}
					if(logger.isDebugEnabled()) {
						logger.debug("invalidate - setting the sessionCreatingTransactionRequest to null, id:" + this.getId());
					}
					sessionCreatingTransactionRequest = null;
				}
			}
		}
	}
1323953
public void markAsToBeDeleted(Transaction transaction) throws SIResourceException 
  {
    if (tc.isEntryEnabled())
      SibTr.entry(tc, "markAsToBeDeleted", transaction);
      
    toBeDeleted = Boolean.TRUE;  
    
    try
    {
      requestUpdate(transaction);
    }
    catch (MessageStoreException e)
    {
      // MessageStoreException shouldn't occur so FFDC.
      FFDCFilter.processException(
        e,
        "com.ibm.ws.sib.processor.impl.store.itemstreams.MQLinkPubSubBridgeItemStream.markAsToBeDeleted",
        "1:151:1.16",
        this);
        
      SibTr.exception(tc, e);
      
      if (tc.isEntryEnabled())
        SibTr.exit(tc, "markAsToBeDeleted", e);
      
      throw new SIResourceException(e);
    }
    
    if (tc.isEntryEnabled())
      SibTr.exit(tc, "markAsToBeDeleted");
      
    return;
  }
875093
public int delete(DatabaseConnection databaseConnection, PreparedDelete<T> preparedDelete) throws SQLException {
		CompiledStatement compiledStatement = preparedDelete.compile(databaseConnection, StatementType.DELETE);
		try {
			int result = compiledStatement.runUpdate();
			if (dao != null && !localIsInBatchMode.get()) {
				dao.notifyChanges();
			}
			return result;
		} finally {
			IOUtils.closeThrowSqlException(compiledStatement, "compiled statement");
		}
	}