Exemple #1
0
        /// <summary>
        /// Perform an actual commit on the given transaction.
        /// </summary>
        /// <param name="status">The status representation of the transaction.</param>
        /// <remarks>
        /// <p>
        /// An implementation does not need to check the rollback-only flag.
        /// </p>
        /// </remarks>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// In the case of system errors.
        /// </exception>
        protected override void DoCommit(DefaultTransactionStatus status)
        {
            HibernateTransactionObject txObject = (HibernateTransactionObject)status.Transaction;

            if (status.Debug)
            {
                log.Debug("Committing Hibernate transaction on Session [" +
                          txObject.SessionHolder.Session + "]");
            }
            try
            {
                txObject.SessionHolder.Transaction.Commit();
            }
            // Note, unfortunate collision of namespaces/classname for NHibernate.TransactionException
            // and Spring.Data.NHibernate requires this wierd construct.
            catch (Exception ex)
            {
                Type nhibTxExceptiontype = TypeResolutionUtils.ResolveType("NHibernate.TransactionException, NHibernate");
                if (ex.GetType().Equals(nhibTxExceptiontype))
                {
                    // assumably from commit call to the underlying ADO.NET connection
                    throw new TransactionSystemException("Could not commit Hibernate transaction", ex);
                }
                HibernateException hibEx = ex as HibernateException;
                if (hibEx != null)
                {
                    // assumably failed to flush changes to database
                    throw ConvertHibernateAccessException(hibEx);
                }
                throw;
            }
        }
        /// <summary>
        /// Return the current transaction object.
        /// </summary>
        /// <returns>The current transaction object.</returns>
        /// <exception cref="Spring.Transaction.CannotCreateTransactionException">
        /// If transaction support is not available.
        /// </exception>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// In the case of lookup or system errors.
        /// </exception>
        protected override object DoGetTransaction()
        {
            HibernateTransactionObject txObject = new HibernateTransactionObject();

            txObject.SavepointAllowed = NestedTransactionsAllowed;
            if (TransactionSynchronizationManager.HasResource(SessionFactory))
            {
                SessionHolder sessionHolder =
                    (SessionHolder)TransactionSynchronizationManager.GetResource(SessionFactory);
                if (log.IsDebugEnabled)
                {
                    log.Debug("Found thread-bound Session [" + sessionHolder.Session +
                              "] for Hibernate transaction");
                }
                txObject.SetSessionHolder(sessionHolder, false);
                if (DbProvider != null)
                {
                    ConnectionHolder conHolder = (ConnectionHolder)
                                                 TransactionSynchronizationManager.GetResource(DbProvider);
                    txObject.ConnectionHolder = conHolder;
                }
            }
            txObject.PromotableTxScopeTransactionObject = new TxScopeTransactionManager.PromotableTxScopeTransactionObject();

            return(txObject);
        }
Exemple #3
0
        /// <summary>
        /// Perform an actual rollback on the given transaction.
        /// </summary>
        /// <param name="status">The status representation of the transaction.</param>
        /// <remarks>
        /// An implementation does not need to check the new transaction flag.
        /// </remarks>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// In the case of system errors.
        /// </exception>
        protected override void DoRollback(DefaultTransactionStatus status)
        {
            HibernateTransactionObject txObject = (HibernateTransactionObject)status.Transaction;

            if (status.Debug)
            {
                log.Debug("Rolling back Hibernate transaction on Session [" +
                          txObject.SessionHolder.Session + "]");
            }
            try
            {
                txObject.SessionHolder.Transaction.Rollback();
            }
            catch (HibernateTransactionException ex)
            {
                throw new TransactionSystemException("Could not roll back Hibernate transaction", ex);
            }
            catch (HibernateException ex)
            {
                // Shouldn't really happen, as a rollback doesn't cause a flush.
                throw ConvertHibernateAccessException(ex);
            }
            finally
            {
                if (!txObject.NewSessionHolder)
                {
                    // Clear all pending inserts/updates/deletes in the Session.
                    // Necessary for pre-bound Sessions, to avoid inconsistent state.
                    txObject.SessionHolder.Session.Clear();
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Set the given transaction rollback-only. Only called on rollback
        /// if the current transaction takes part in an existing one.
        /// </summary>
        /// <param name="status">The status representation of the transaction.</param>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// In the case of system errors.
        /// </exception>
        protected override void DoSetRollbackOnly(DefaultTransactionStatus status)
        {
            HibernateTransactionObject txObject = (HibernateTransactionObject)status.Transaction;

            if (status.Debug)
            {
                log.Debug("Setting Hibernate transaction on Session [" +
                          txObject.SessionHolder.Session + "] rollback-only");
            }
            txObject.SetRollbackOnly();
        }
        /// <summary>
        /// Cleanup resources after transaction completion.
        /// </summary>
        /// <param name="transaction">Transaction object returned by
        /// <see cref="M:Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.</param>
        /// <remarks>
        /// <note>
        /// This implemenation unbinds the SessionFactory and
        /// DbProvider from thread local storage and closes the
        /// ISession.
        /// </note>
        ///     <p>
        /// Called after <see cref="M:Spring.Transaction.Support.AbstractPlatformTransactionManager.DoCommit(Spring.Transaction.Support.DefaultTransactionStatus)"/>
        /// and
        /// <see cref="M:Spring.Transaction.Support.AbstractPlatformTransactionManager.DoRollback(Spring.Transaction.Support.DefaultTransactionStatus)"/>
        /// execution on any outcome.
        /// </p>
        ///     <p>
        /// Should not throw any exceptions but just issue warnings on errors.
        /// </p>
        /// </remarks>
        protected override void DoCleanupAfterCompletion(object transaction)
        {
            HibernateTransactionObject txObject = (HibernateTransactionObject)transaction;

            // Remove the session holder from the thread.
            if (txObject.NewSessionHolder)
            {
                TransactionSynchronizationManager.UnbindResource(SessionFactory);
            }
            // Remove the ADO.NET connection holder from the thread, if exposed.
            if (DbProvider != null)
            {
                TransactionSynchronizationManager.UnbindResource(DbProvider);
            }

            /*
             * try
             * {
             *  //TODO investigate isolation level settings...
             *  //IDbConnection con = txObject.SessionHolder.Session.Connection;
             *  //AdoUtils.ResetConnectionAfterTransaction(con, txObject.PreviousIsolationLevel);
             * }
             * catch (HibernateException ex)
             * {
             *  log.Info("Could not access ADO.NET IDbConnection of Hibernate Session", ex);
             * }
             */
            ISession session = txObject.SessionHolder.Session;

            if (txObject.NewSessionHolder)
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug("Closing Hibernate Session [" + session + "] after transaction");
                }

                SessionFactoryUtils.CloseSessionOrRegisterDeferredClose(session, SessionFactory);
            }
            else
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug("Not closing pre-bound Hibernate Session [" + session + "] after transaction");
                }
                if (txObject.SessionHolder.AssignedPreviousFlushMode)
                {
                    session.FlushMode = txObject.SessionHolder.PreviousFlushMode;
                }
            }

            txObject.SessionHolder.Clear();
        }
        /// <summary>
        /// Suspend the resources of the current transaction.
        /// </summary>
        /// <param name="transaction">
        /// Transaction object returned by
        /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.
        /// </param>
        /// <returns>
        /// An object that holds suspended resources (will be kept unexamined for passing it into
        /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoResume"/>.)
        /// </returns>
        /// <remarks>
        /// Transaction synchronization will already have been suspended.
        /// </remarks>
        /// <exception cref="Spring.Transaction.IllegalTransactionStateException">
        /// If suspending is not supported by the transaction manager implementation.
        /// </exception>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// in case of system errors.
        /// </exception>
        protected override object DoSuspend(object transaction)
        {
            HibernateTransactionObject txObject = (HibernateTransactionObject)transaction;

            txObject.SetSessionHolder(null, false);
            SessionHolder sessionHolder =
                (SessionHolder)TransactionSynchronizationManager.UnbindResource(SessionFactory);
            ConnectionHolder connectionHolder = null;

            if (DbProvider != null)
            {
                connectionHolder = (ConnectionHolder)TransactionSynchronizationManager.UnbindResource(DbProvider);
            }
            return(new SuspendedResourcesHolder(sessionHolder, connectionHolder));
        }
Exemple #7
0
        /// <summary>
        /// Cleanup resources after transaction completion.
        /// </summary>
        /// <param name="transaction">Transaction object returned by
        /// <see cref="M:Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.</param>
        /// <remarks>
        /// <note>
        /// This implemenation unbinds the SessionFactory and
        /// DbProvider from thread local storage and closes the
        /// ISession.
        /// </note>
        ///     <p>
        /// Called after <see cref="M:Spring.Transaction.Support.AbstractPlatformTransactionManager.DoCommit(Spring.Transaction.Support.DefaultTransactionStatus)"/>
        /// and
        /// <see cref="M:Spring.Transaction.Support.AbstractPlatformTransactionManager.DoRollback(Spring.Transaction.Support.DefaultTransactionStatus)"/>
        /// execution on any outcome.
        /// </p>
        ///     <p>
        /// Should not throw any exceptions but just issue warnings on errors.
        /// </p>
        /// </remarks>
        protected override void DoCleanupAfterCompletion(object transaction)
        {
            HibernateTransactionObject txObject = (HibernateTransactionObject)transaction;

            // Remove the session holder from the thread.
            if (txObject.NewSessionHolder)
            {
                TransactionSynchronizationManager.UnbindResource(SessionFactory);
            }
            // Remove the ADO.NET connection holder from the thread, if exposed.
            if (DbProvider != null)
            {
                TransactionSynchronizationManager.UnbindResource(DbProvider);
            }

            ISession session = txObject.SessionHolder.Session;

            if (txObject.NewSessionHolder)
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug("Closing Hibernate Session [" + session + "] after transaction");
                }
                SessionFactoryUtils.CloseSessionOrRegisterDeferredClose(session, SessionFactory);
            }
            else
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug("Not closing pre-bound Hibernate Session [" + session + "] after transaction");
                }
                if (txObject.SessionHolder.AssignedPreviousFlushMode)
                {
                    session.FlushMode = txObject.SessionHolder.PreviousFlushMode;
                }
            }
            txObject.SessionHolder.Clear();
        }
        /// <summary>
        /// Perform an actual rollback on the given transaction.
        /// </summary>
        /// <param name="status">The status representation of the transaction.</param>
        /// <remarks>
        /// An implementation does not need to check the new transaction flag.
        /// </remarks>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// In the case of system errors.
        /// </exception>
        protected override void DoRollback(DefaultTransactionStatus status)
        {
            HibernateTransactionObject txObject = (HibernateTransactionObject)status.Transaction;

            if (!txObject.NewSessionHolder)
            {
                // Clear all pending inserts/updates/deletes in the Session.
                // Necessary for pre-bound Sessions, to avoid inconsistent state.
                txObject.SessionHolder.Session.Clear();
            }

            DoTxScopeRollback(status);
            return;


/*            HibernateTransactionObject txObject = (HibernateTransactionObject)status.Transaction;
 *
 *          if (status.Debug)
 *          {
 *              log.Debug("Rolling back Hibernate transaction on Session [" +
 *                  txObject.SessionHolder.Session + "]");
 *          }
 *          try
 *          {
 *              if (txObject.SessionHolder.Session != null && txObject.SessionHolder.Transaction != null && !txObject.SessionHolder.Transaction.IsActive)
 *              {
 *                  return;
 *              }
 *
 *              IDbTransaction adoTx = GetIDbTransaction(txObject.SessionHolder.Transaction);
 *
 *              if (adoTx != null && adoTx.Connection != null)
 *              {
 *                  txObject.SessionHolder.Transaction.Rollback();
 *              }
 *              else
 *              {
 *                  if (status.Debug)
 *                  {
 *                      log.Debug("Unable to RollBack Hibernate transaction; connection for Hibernate transaction on Session [" +
 *                          txObject.SessionHolder.Session + "] was null");
 *                  }
 *              }
 *
 *          }
 *          catch (HibernateTransactionException ex)
 *          {
 *              throw new TransactionSystemException("Could not roll back Hibernate transaction", ex);
 *          }
 *          catch (HibernateException ex)
 *          {
 *              // Shouldn't really happen, as a rollback doesn't cause a flush.
 *              throw ConvertHibernateAccessException(ex);
 *          }
 *          finally
 *          {
 *              if (!txObject.NewSessionHolder)
 *              {
 *                  // Clear all pending inserts/updates/deletes in the Session.
 *                  // Necessary for pre-bound Sessions, to avoid inconsistent state.
 *                  txObject.SessionHolder.Session.Clear();
 *              }
 *              DoTxScopeRollback(status);
 *          }*/
        }
        /// <summary>
        /// Begin a new transaction with the given transaction definition.
        /// </summary>
        /// <param name="transaction">
        /// Transaction object returned by
        /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.
        /// </param>
        /// <param name="definition">
        /// <see cref="Spring.Transaction.ITransactionDefinition"/> instance, describing
        /// propagation behavior, isolation level, timeout etc.
        /// </param>
        /// <remarks>
        /// Does not have to care about applying the propagation behavior,
        /// as this has already been handled by this abstract manager.
        /// </remarks>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// In the case of creation or system errors.
        /// </exception>
        protected override void DoBegin(object transaction, ITransactionDefinition definition)
        {
            TxScopeTransactionManager.PromotableTxScopeTransactionObject promotableTxScopeTransactionObject =
                ((HibernateTransactionObject)transaction).PromotableTxScopeTransactionObject;
            try
            {
                DoTxScopeBegin(promotableTxScopeTransactionObject, definition);
            }
            catch (Exception e)
            {
                throw new CannotCreateTransactionException("Transaction Scope failure on begin", e);
            }

            HibernateTransactionObject txObject = (HibernateTransactionObject)transaction;

            if (DbProvider != null && TransactionSynchronizationManager.HasResource(DbProvider) &&
                !txObject.ConnectionHolder.SynchronizedWithTransaction)
            {
                throw new IllegalTransactionStateException(
                          "Pre-bound ADO.NET Connection found - HibernateTransactionManager does not support " +
                          "running within AdoTransactionManager if told to manage the DbProvider itself. " +
                          "It is recommended to use a single HibernateTransactionManager for all transactions " +
                          "on a single DbProvider, no matter whether Hibernate or ADO.NET access.");
            }
            ISession session = null;

            try
            {
                if (txObject.SessionHolder == null || txObject.SessionHolder.SynchronizedWithTransaction)
                {
                    IInterceptor interceptor = EntityInterceptor;
                    ISession     newSession  = (interceptor != null ?
                                                SessionFactory.OpenSession(interceptor) : SessionFactory.OpenSession());

                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Opened new Session [" + newSession + "] for Hibernate transaction");
                    }
                    txObject.SetSessionHolder(new SessionHolder(newSession), true);
                }
                txObject.SessionHolder.SynchronizedWithTransaction = true;
                session = txObject.SessionHolder.Session;

                IDbConnection con = session.Connection;
                //TODO isolation level mgmt
                //IsolationLevel previousIsolationLevel =

                if (definition.ReadOnly && txObject.NewSessionHolder)
                {
                    // Just set to NEVER in case of a new Session for this transaction.
                    session.FlushMode = FlushMode.Never;
                }

                if (!definition.ReadOnly && !txObject.NewSessionHolder)
                {
                    // We need AUTO or COMMIT for a non-read-only transaction.
                    FlushMode flushMode = session.FlushMode;
                    if (FlushMode.Never == flushMode)
                    {
                        session.FlushMode = FlushMode.Auto;
                        txObject.SessionHolder.PreviousFlushMode = flushMode;
                    }
                }

                // Add the Hibernate transaction to the session holder.
                // for now pass in tx options isolation level.
                ITransaction   hibernateTx = session.BeginTransaction(definition.TransactionIsolationLevel);
                IDbTransaction adoTx       = GetIDbTransaction(hibernateTx);

                // Add the Hibernate transaction to the session holder.
                txObject.SessionHolder.Transaction = hibernateTx;

                // Register transaction timeout.
                int timeout = DetermineTimeout(definition);
                if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT)
                {
                    txObject.SessionHolder.TimeoutInSeconds = timeout;
                }

                // Register the Hibernate Session's ADO.NET Connection/TX pair for the DbProvider, if set.
                if (DbProvider != null)
                {
                    //investigate passing null for tx.
                    ConnectionHolder conHolder = new ConnectionHolder(con, adoTx);
                    if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT)
                    {
                        conHolder.TimeoutInMillis = definition.TransactionTimeout;
                    }
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Exposing Hibernate transaction as ADO transaction [" + con + "]");
                    }
                    TransactionSynchronizationManager.BindResource(DbProvider, conHolder);
                    txObject.ConnectionHolder = conHolder;
                }

                // Bind the session holder to the thread.
                if (txObject.NewSessionHolder)
                {
                    TransactionSynchronizationManager.BindResource(SessionFactory, txObject.SessionHolder);
                }
            }
            catch (Exception ex)
            {
                SessionFactoryUtils.CloseSession(session);
                throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex);
            }
        }
 /// <summary>
 /// Return the current transaction object.
 /// </summary>
 /// <returns>The current transaction object.</returns>
 /// <exception cref="Spring.Transaction.CannotCreateTransactionException">
 /// If transaction support is not available.
 /// </exception>
 /// <exception cref="Spring.Transaction.TransactionException">
 /// In the case of lookup or system errors.
 /// </exception>
 protected override object DoGetTransaction()
 {
     HibernateTransactionObject txObject = new HibernateTransactionObject();
     txObject.SavepointAllowed = NestedTransactionsAllowed;
     if (TransactionSynchronizationManager.HasResource(SessionFactory))
     {
         SessionHolder sessionHolder =
             (SessionHolder)TransactionSynchronizationManager.GetResource(SessionFactory);
         if (log.IsDebugEnabled)
         {
             log.Debug("Found thread-bound Session [" + sessionHolder.Session +
                 "] for Hibernate transaction");
         }
         txObject.SetSessionHolder(sessionHolder, false);
         if (DbProvider != null)
         {
             ConnectionHolder conHolder = (ConnectionHolder)
                 TransactionSynchronizationManager.GetResource(DbProvider);
             txObject.ConnectionHolder = conHolder;
         }
     }
     return txObject;
 }