/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2011, Red Hat Inc. or third-party contributors as
 * indicated by the @author tags or express copyright attribution
 * statements applied by the authors.  All third-party contributions are
 * distributed under license by Red Hat Inc.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package org.hibernate.engine.transaction.spi;

import javax.transaction.Status;
import javax.transaction.Synchronization;

import org.hibernate.HibernateException;
import org.hibernate.TransactionException;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.internal.CoreLogging;

import org.jboss.logging.Logger;

Abstract support for creating transaction implementations
Author:Steve Ebersole
/** * Abstract support for creating {@link TransactionImplementor transaction} implementations * * @author Steve Ebersole */
public abstract class AbstractTransactionImpl implements TransactionImplementor { private static final Logger LOG = CoreLogging.logger( AbstractTransactionImpl.class ); private final TransactionCoordinator transactionCoordinator; private boolean valid = true; private LocalStatus localStatus = LocalStatus.NOT_ACTIVE; private int timeout = -1; protected AbstractTransactionImpl(TransactionCoordinator transactionCoordinator) { this.transactionCoordinator = transactionCoordinator; } @Override public void invalidate() { valid = false; }
Perform the actual steps of beginning a transaction according to the strategy.
Throws:
  • TransactionException – Indicates a problem beginning the transaction
/** * Perform the actual steps of beginning a transaction according to the strategy. * * @throws org.hibernate.TransactionException Indicates a problem beginning the transaction */
protected abstract void doBegin();
Perform the actual steps of committing a transaction according to the strategy.
Throws:
  • TransactionException – Indicates a problem committing the transaction
/** * Perform the actual steps of committing a transaction according to the strategy. * * @throws org.hibernate.TransactionException Indicates a problem committing the transaction */
protected abstract void doCommit();
Perform the actual steps of rolling back a transaction according to the strategy.
Throws:
  • TransactionException – Indicates a problem rolling back the transaction
/** * Perform the actual steps of rolling back a transaction according to the strategy. * * @throws org.hibernate.TransactionException Indicates a problem rolling back the transaction */
protected abstract void doRollback(); protected abstract void afterTransactionBegin(); protected abstract void beforeTransactionCommit(); protected abstract void beforeTransactionRollBack(); protected abstract void afterTransactionCompletion(int status); protected abstract void afterAfterCompletion();
Provide subclasses with access to the transaction coordinator.
Returns:This transaction's context.
/** * Provide subclasses with access to the transaction coordinator. * * @return This transaction's context. */
protected TransactionCoordinator transactionCoordinator() { return transactionCoordinator; }
Provide subclasses with convenient access to the configured JtaPlatform
Returns:The JtaPlatform
/** * Provide subclasses with convenient access to the configured {@link JtaPlatform} * * @return The {@link org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform} */
protected JtaPlatform jtaPlatform() { return transactionCoordinator().getTransactionContext().getTransactionEnvironment().getJtaPlatform(); } @Override public void registerSynchronization(Synchronization synchronization) { transactionCoordinator().getSynchronizationRegistry().registerSynchronization( synchronization ); } @Override public LocalStatus getLocalStatus() { return localStatus; } @Override public boolean isActive() { return localStatus == LocalStatus.ACTIVE && doExtendedActiveCheck(); } @Override public boolean isParticipating() { return getJoinStatus() == JoinStatus.JOINED && isActive(); } @Override public boolean wasCommitted() { return localStatus == LocalStatus.COMMITTED; } @Override public boolean wasRolledBack() throws HibernateException { return localStatus == LocalStatus.ROLLED_BACK; }
Active has been checked against local state. Perform any needed checks against resource transactions.
Returns:true if the extended active check checks out as well; false otherwise.
/** * Active has been checked against local state. Perform any needed checks against resource transactions. * * @return {@code true} if the extended active check checks out as well; false otherwise. */
protected boolean doExtendedActiveCheck() { return true; } @Override public void begin() throws HibernateException { if ( !valid ) { throw new TransactionException( "Transaction instance is no longer valid" ); } if ( localStatus == LocalStatus.ACTIVE ) { throw new TransactionException( "nested transactions not supported" ); } if ( localStatus != LocalStatus.NOT_ACTIVE ) { throw new TransactionException( "reuse of Transaction instances not supported" ); } LOG.debug( "begin" ); doBegin(); localStatus = LocalStatus.ACTIVE; afterTransactionBegin(); } @Override public void commit() throws HibernateException { if ( localStatus != LocalStatus.ACTIVE ) { throw new TransactionException( "Transaction not successfully started" ); } LOG.debug( "committing" ); beforeTransactionCommit(); try { doCommit(); localStatus = LocalStatus.COMMITTED; afterTransactionCompletion( Status.STATUS_COMMITTED ); } catch (Exception e) { localStatus = LocalStatus.FAILED_COMMIT; afterTransactionCompletion( Status.STATUS_UNKNOWN ); throw new TransactionException( "commit failed", e ); } finally { invalidate(); afterAfterCompletion(); } } protected boolean allowFailedCommitToPhysicallyRollback() { return false; } @Override public void rollback() throws HibernateException { if ( localStatus != LocalStatus.ACTIVE && localStatus != LocalStatus.FAILED_COMMIT ) { throw new TransactionException( "Transaction not successfully started" ); } LOG.debug( "rolling back" ); beforeTransactionRollBack(); if ( localStatus != LocalStatus.FAILED_COMMIT || allowFailedCommitToPhysicallyRollback() ) { try { doRollback(); localStatus = LocalStatus.ROLLED_BACK; afterTransactionCompletion( Status.STATUS_ROLLEDBACK ); } catch (Exception e) { afterTransactionCompletion( Status.STATUS_UNKNOWN ); throw new TransactionException( "rollback failed", e ); } finally { invalidate(); afterAfterCompletion(); } } } @Override public void setTimeout(int seconds) { timeout = seconds; } @Override public int getTimeout() { return timeout; } @Override public void markForJoin() { // generally speaking this is no-op } @Override public void join() { // generally speaking this is no-op } @Override public void resetJoinStatus() { // generally speaking this is no-op } }