`
dingchao.lonton
  • 浏览: 49771 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

spring transation源代码研读笔记

 
阅读更多

最近研读了spring的Transaction的源代码,顺便做个笔记,以防时间长了忘记。

 

我们知道如果用编码的方式来写spring的事物管理,代码其实是这样子的

 

 

PlatformTransactionManager transactionManager = new xxxTransactionManager();

TransactionDefinition transactionDefinition = new DefultTransactionDefinition ();

TransactionStatus status = transactionManager .getTransaction(transactionDefinition);

try{
//business code goes here

transactionManager .commit(status );

}catch(Exception){
//business code goes here 

transactionManager .rollback(status );
}finally{
    ...
}

 

 

所以我们的分析起始点是从TransactionStatus status = transactionManager .getTransaction(transactionDefinition); 这一句开始 。 

 

经过查找,这个方法最终是在AbstractPlatformTransactionManager 中实现的,下面我们来看一看这个方法的具体实现,(顺便说一句,其实在spring中,只要以Abstract开头的类其实都是一个模板类,这个模板类的的公用方法都已经实现)

 

打开这个方法,我们可以看见

 

/**
	 * This implementation handles propagation behavior. Delegates to
	 * <code>doGetTransaction</code>, <code>isExistingTransaction</code>
	 * and <code>doBegin</code>.
	 * @see #doGetTransaction
	 * @see #isExistingTransaction
	 * @see #doBegin
	 */
	public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
		Object transaction = doGetTransaction();

		// Cache debug flag to avoid repeated checks.
		boolean debugEnabled = logger.isDebugEnabled();

		if (definition == null) {
			// Use defaults if no transaction definition given.
			definition = new DefaultTransactionDefinition();
		}

		if (isExistingTransaction(transaction)) {
			// Existing transaction found -> check propagation behavior to find out how to behave.
			return handleExistingTransaction(definition, transaction, debugEnabled);
		}

		// Check definition settings for new transaction.
		if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
		}

		// No existing transaction found -> check propagation behavior to find out how to proceed.
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
		    definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			SuspendedResourcesHolder suspendedResources = suspend(null);
			if (debugEnabled) {
				logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
			}
			try {
				doBegin(transaction, definition);
			}
			catch (RuntimeException ex) {
				resume(null, suspendedResources);
				throw ex;
			}
			catch (Error err) {
				resume(null, suspendedResources);
				throw err;
			}
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			return newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
		}
		else {
			// Create "empty" transaction: no actual transaction, but potentially synchronization.
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return newTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
		}
	}

 

 

这个方法里的有3个方法是代理到子类里面去实现的 ,他们分别是doGetTransaction , isExistingTransaction,doBegin

 

我们一Hibernate作为一个例子来讲解

 

在AbstractPlatformTransactionManager 中,doGetTransaction 是一个抽象函数 :

 

/**
	 * Return a transaction object for the current transaction state.
	 * <p>The returned object will usually be specific to the concrete transaction
	 * manager implementation, carrying corresponding transaction state in a
	 * modifiable fashion. This object will be passed into the other template
	 * methods (e.g. doBegin and doCommit), either directly or as part of a
	 * DefaultTransactionStatus instance.
	 * <p>The returned object should contain information about any existing
	 * transaction, that is, a transaction that has already started before the
	 * current <code>getTransaction</code> call on the transaction manager.
	 * Consequently, a <code>doGetTransaction</code> implementation will usually
	 * look for an existing transaction and store corresponding state in the
	 * returned transaction object.
	 * @return the current transaction object
	 * @throws org.springframework.transaction.CannotCreateTransactionException
	 * if transaction support is not available
	 * @throws TransactionException in case of lookup or system errors
	 * @see #doBegin
	 * @see #doCommit
	 * @see #doRollback
	 * @see DefaultTransactionStatus#getTransaction
	 */
	protected abstract Object doGetTransaction() throws TransactionException;

 

 

所以这个方法会在他的子类里面实现, 我们可以在 HibernateTransactionManager 中找到他的具体实现

 

 

protected Object doGetTransaction() {
		HibernateTransactionObject txObject = new HibernateTransactionObject();
		txObject.setSavepointAllowed(isNestedTransactionAllowed());

		SessionHolder sessionHolder =
				(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
		if (sessionHolder != null) {
			if (logger.isDebugEnabled()) {
				logger.debug("Found thread-bound Session [" +
						SessionFactoryUtils.toString(sessionHolder.getSession()) + "] for Hibernate transaction");
			}
			txObject.setSessionHolder(sessionHolder);
		}
		else if (this.hibernateManagedSession) {
			try {
				Session session = getSessionFactory().getCurrentSession();
				if (logger.isDebugEnabled()) {
					logger.debug("Found Hibernate-managed Session [" +
							SessionFactoryUtils.toString(session) + "] for Spring-managed transaction");
				}
				txObject.setExistingSession(session);
			}
			catch (HibernateException ex) {
				throw new DataAccessResourceFailureException(
						"Could not obtain Hibernate-managed Session for Spring-managed transaction", ex);
			}
		}

		if (getDataSource() != null) {
			ConnectionHolder conHolder = (ConnectionHolder)
					TransactionSynchronizationManager.getResource(getDataSource());
			txObject.setConnectionHolder(conHolder);
		}

		return txObject;
	}

 

 HibernateTransactionObject txObject = new HibernateTransactionObject(); 这句话是获取一个Hibernate的事物对象,这个事物对象里面包含什么信息呢,我们打开这个类看看就知道了

 

 

/**
	 * Hibernate transaction object, representing a SessionHolder.
	 * Used as transaction object by HibernateTransactionManager.
	 */
	private static class HibernateTransactionObject extends JdbcTransactionObjectSupport {

		private SessionHolder sessionHolder;

		private boolean newSessionHolder;

		private boolean newSession;

		public void setSession(Session session) {
			this.sessionHolder = new SessionHolder(session);
			this.newSessionHolder = true;
			this.newSession = true;
		}

		public void setExistingSession(Session session) {
			this.sessionHolder = new SessionHolder(session);
			this.newSessionHolder = true;
			this.newSession = false;
		}

		public void setSessionHolder(SessionHolder sessionHolder) {
			this.sessionHolder = sessionHolder;
			this.newSessionHolder = false;
			this.newSession = false;
		}

		public SessionHolder getSessionHolder() {
			return this.sessionHolder;
		}

		public boolean isNewSessionHolder() {
			return this.newSessionHolder;
		}

		public boolean isNewSession() {
			return this.newSession;
		}

		public boolean hasSpringManagedTransaction() {
			return (this.sessionHolder != null && this.sessionHolder.getTransaction() != null);
		}

		public boolean hasHibernateManagedTransaction() {
			return (this.sessionHolder != null && this.sessionHolder.getSession().getTransaction().isActive());
		}

		public void setRollbackOnly() {
			getSessionHolder().setRollbackOnly();
			if (hasConnectionHolder()) {
				getConnectionHolder().setRollbackOnly();
			}
		}

		public boolean isRollbackOnly() {
			return getSessionHolder().isRollbackOnly() ||
					(hasConnectionHolder() && getConnectionHolder().isRollbackOnly());
		}
	}
 

 

 

他有3个属性分别是 private SessionHolder sessionHolder; private boolean newSessionHolder;private boolean newSession; 最重要一个属性就是 sessionHolder ,我们一看名称就知道他的含义,session的保持者,因为事物的最初的原则就是,在一个session之内才能完成一个事物,所以在事物的整个过程中,我们必须保持这个session的一致;

 

我们在来看看这一句 SessionHolder sessionHolder =

(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());

 

这句话会初始化一个sessionHolder ,要想一看究竟,进入getResource 来看看

 

 

public abstract class TransactionSynchronizationManager {

	private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);

	private static final Comparator synchronizationComparator = new OrderComparator();

	private static final ThreadLocal resources =
			new NamedThreadLocal("Transactional resources");

	private static final ThreadLocal synchronizations =
			new NamedThreadLocal("Transaction synchronizations");

	private static final ThreadLocal currentTransactionName =
			new NamedThreadLocal("Current transaction name");

	private static final ThreadLocal currentTransactionReadOnly =
			new NamedThreadLocal("Current transaction read-only status");

	private static final ThreadLocal currentTransactionIsolationLevel =
			new NamedThreadLocal("Current transaction isolation level");

	private static final ThreadLocal actualTransactionActive =
			new NamedThreadLocal("Actual transaction active");


	//-------------------------------------------------------------------------
	// Management of transaction-associated resource handles
	//-------------------------------------------------------------------------

	/**
	 * Return all resources that are bound to the current thread.
	 * <p>Mainly for debugging purposes. Resource managers should always invoke
	 * <code>hasResource</code> for a specific resource key that they are interested in.
	 * @return a Map with resource keys (usually the resource factory) and resource
	 * values (usually the active resource object), or an empty Map if there are
	 * currently no resources bound
	 * @see #hasResource
	 */
	public static Map getResourceMap() {
		Map map = (Map) resources.get();
		return (map != null ? Collections.unmodifiableMap(map) : Collections.EMPTY_MAP);
	}

	/**
	 * Check if there is a resource for the given key bound to the current thread.
	 * @param key the key to check (usually the resource factory)
	 * @return if there is a value bound to the current thread
	 * @see ResourceTransactionManager#getResourceFactory() 
	 */
	public static boolean hasResource(Object key) {
		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
		Object value = doGetResource(actualKey);
		return (value != null);
	}

	/**
	 * Retrieve a resource for the given key that is bound to the current thread.
	 * @param key the key to check (usually the resource factory)
	 * @return a value bound to the current thread (usually the active
	 * resource object), or <code>null</code> if none
	 * @see ResourceTransactionManager#getResourceFactory()
	 */
	public static Object getResource(Object key) {
		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
		Object value = doGetResource(actualKey);
		if (value != null && logger.isTraceEnabled()) {
			logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" +
					Thread.currentThread().getName() + "]");
		}
		return value;
	}

	/**
	 * Actually check the value of the resource that is bound for the given key.
	 */
	private static Object doGetResource(Object actualKey) {
		Map map = (Map) resources.get();
		if (map == null) {
			return null;
		}
		Object value = map.get(actualKey);
		// Transparently remove ResourceHolder that was marked as void...
		if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
			map.remove(actualKey);
			value = null;
		}
		return value;
	}

	/**
	 * Bind the given resource for the given key to the current thread.
	 * @param key the key to bind the value to (usually the resource factory)
	 * @param value the value to bind (usually the active resource object)
	 * @throws IllegalStateException if there is already a value bound to the thread
	 * @see ResourceTransactionManager#getResourceFactory()
	 */
	public static void bindResource(Object key, Object value) throws IllegalStateException {
		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
		Assert.notNull(value, "Value must not be null");
		Map map = (Map) resources.get();
		// set ThreadLocal Map if none found
		if (map == null) {
			map = new HashMap();
			resources.set(map);
		}
		if (map.put(actualKey, value) != null) {
			throw new IllegalStateException("Already value [" + map.get(actualKey) + "] for key [" +
					actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
		}
		if (logger.isTraceEnabled()) {
			logger.trace("Bound value [" + value + "] for key [" + actualKey + "] to thread [" +
					Thread.currentThread().getName() + "]");
		}
	}

	/**
	 * Unbind a resource for the given key from the current thread.
	 * @param key the key to unbind (usually the resource factory)
	 * @return the previously bound value (usually the active resource object)
	 * @throws IllegalStateException if there is no value bound to the thread
	 * @see ResourceTransactionManager#getResourceFactory()
	 */
	public static Object unbindResource(Object key) throws IllegalStateException {
		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
		Object value = doUnbindResource(actualKey);
		if (value == null) {
			throw new IllegalStateException(
					"No value for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
		}
		return value;
	}

	/**
	 * Unbind a resource for the given key from the current thread.
	 * @param key the key to unbind (usually the resource factory)
	 * @return the previously bound value, or <code>null</code> if none bound
	 */
	public static Object unbindResourceIfPossible(Object key) {
		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
		return doUnbindResource(actualKey);
	}

	/**
	 * Actually remove the value of the resource that is bound for the given key.
	 */
	private static Object doUnbindResource(Object actualKey) {
		Map map = (Map) resources.get();
		if (map == null) {
			return null;
		}
		Object value = map.remove(actualKey);
		// Remove entire ThreadLocal if empty...
		if (map.isEmpty()) {
			resources.set(null);
		}
		if (value != null && logger.isTraceEnabled()) {
			logger.trace("Removed value [" + value + "] for key [" + actualKey + "] from thread [" +
					Thread.currentThread().getName() + "]");
		}
		return value;
	}


	//-------------------------------------------------------------------------
	// Management of transaction synchronizations
	//-------------------------------------------------------------------------

	/**
	 * Return if transaction synchronization is active for the current thread.
	 * Can be called before register to avoid unnecessary instance creation.
	 * @see #registerSynchronization
	 */
	public static boolean isSynchronizationActive() {
		return (synchronizations.get() != null);
	}

	/**
	 * Activate transaction synchronization for the current thread.
	 * Called by a transaction manager on transaction begin.
	 * @throws IllegalStateException if synchronization is already active
	 */
	public static void initSynchronization() throws IllegalStateException {
		if (isSynchronizationActive()) {
			throw new IllegalStateException("Cannot activate transaction synchronization - already active");
		}
		logger.trace("Initializing transaction synchronization");
		synchronizations.set(new LinkedList());
	}

	/**
	 * Register a new transaction synchronization for the current thread.
	 * Typically called by resource management code.
	 * <p>Note that synchronizations can implement the
	 * {@link org.springframework.core.Ordered} interface.
	 * They will be executed in an order according to their order value (if any).
	 * @param synchronization the synchronization object to register
	 * @throws IllegalStateException if transaction synchronization is not active
	 * @see org.springframework.core.Ordered
	 */
	public static void registerSynchronization(TransactionSynchronization synchronization)
	    throws IllegalStateException {

		Assert.notNull(synchronization, "TransactionSynchronization must not be null");
		if (!isSynchronizationActive()) {
			throw new IllegalStateException("Transaction synchronization is not active");
		}
		List synchs = (List) synchronizations.get();
		synchs.add(synchronization);
	}

	/**
	 * Return an unmodifiable snapshot list of all registered synchronizations
	 * for the current thread.
	 * @return unmodifiable List of TransactionSynchronization instances
	 * @throws IllegalStateException if synchronization is not active
	 * @see TransactionSynchronization
	 */
	public static List getSynchronizations() throws IllegalStateException {
		if (!isSynchronizationActive()) {
			throw new IllegalStateException("Transaction synchronization is not active");
		}
		List synchs = (List) synchronizations.get();
		// Sort lazily here, not in registerSynchronization.
		Collections.sort(synchs, synchronizationComparator);
		// Return unmodifiable snapshot, to avoid ConcurrentModificationExceptions
		// while iterating and invoking synchronization callbacks that in turn
		// might register further synchronizations.
		return Collections.unmodifiableList(new ArrayList(synchs));
	}

	/**
	 * Deactivate transaction synchronization for the current thread.
	 * Called by the transaction manager on transaction cleanup.
	 * @throws IllegalStateException if synchronization is not active
	 */
	public static void clearSynchronization() throws IllegalStateException {
		if (!isSynchronizationActive()) {
			throw new IllegalStateException("Cannot deactivate transaction synchronization - not active");
		}
		logger.trace("Clearing transaction synchronization");
		synchronizations.set(null);
	}


	//-------------------------------------------------------------------------
	// Exposure of transaction characteristics
	//-------------------------------------------------------------------------

	/**
	 * Expose the name of the current transaction, if any.
	 * Called by the transaction manager on transaction begin and on cleanup.
	 * @param name the name of the transaction, or <code>null</code> to reset it
	 * @see org.springframework.transaction.TransactionDefinition#getName()
	 */
	public static void setCurrentTransactionName(String name) {
		currentTransactionName.set(name);
	}

	/**
	 * Return the name of the current transaction, or <code>null</code> if none set.
	 * To be called by resource management code for optimizations per use case,
	 * for example to optimize fetch strategies for specific named transactions.
	 * @see org.springframework.transaction.TransactionDefinition#getName()
	 */
	public static String getCurrentTransactionName() {
		return (String) currentTransactionName.get();
	}

	/**
	 * Expose a read-only flag for the current transaction.
	 * Called by the transaction manager on transaction begin and on cleanup.
	 * @param readOnly <code>true</code> to mark the current transaction
	 * as read-only; <code>false</code> to reset such a read-only marker
	 * @see org.springframework.transaction.TransactionDefinition#isReadOnly()
	 */
	public static void setCurrentTransactionReadOnly(boolean readOnly) {
		currentTransactionReadOnly.set(readOnly ? Boolean.TRUE : null);
	}

	/**
	 * Return whether the current transaction is marked as read-only.
	 * To be called by resource management code when preparing a newly
	 * created resource (for example, a Hibernate Session).
	 * <p>Note that transaction synchronizations receive the read-only flag
	 * as argument for the <code>beforeCommit</code> callback, to be able
	 * to suppress change detection on commit. The present method is meant
	 * to be used for earlier read-only checks, for example to set the
	 * flush mode of a Hibernate Session to "FlushMode.NEVER" upfront.
	 * @see org.springframework.transaction.TransactionDefinition#isReadOnly()
	 * @see TransactionSynchronization#beforeCommit(boolean)
	 * @see org.hibernate.Session#flush
	 * @see org.hibernate.Session#setFlushMode
	 * @see org.hibernate.FlushMode#NEVER
	 */
	public static boolean isCurrentTransactionReadOnly() {
		return (currentTransactionReadOnly.get() != null);
	}

	/**
	 * Expose an isolation level for the current transaction.
	 * Called by the transaction manager on transaction begin and on cleanup.
	 * @param isolationLevel the isolation level to expose, according to the
	 * JDBC Connection constants (equivalent to the corresponding Spring
	 * TransactionDefinition constants), or <code>null</code> to reset it
	 * @see java.sql.Connection#TRANSACTION_READ_UNCOMMITTED
	 * @see java.sql.Connection#TRANSACTION_READ_COMMITTED
	 * @see java.sql.Connection#TRANSACTION_REPEATABLE_READ
	 * @see java.sql.Connection#TRANSACTION_SERIALIZABLE
	 * @see org.springframework.transaction.TransactionDefinition#ISOLATION_READ_UNCOMMITTED
	 * @see org.springframework.transaction.TransactionDefinition#ISOLATION_READ_COMMITTED
	 * @see org.springframework.transaction.TransactionDefinition#ISOLATION_REPEATABLE_READ
	 * @see org.springframework.transaction.TransactionDefinition#ISOLATION_SERIALIZABLE
	 * @see org.springframework.transaction.TransactionDefinition#getIsolationLevel()
	 */
	public static void setCurrentTransactionIsolationLevel(Integer isolationLevel) {
		currentTransactionIsolationLevel.set(isolationLevel);
	}

	/**
	 * Return the isolation level for the current transaction, if any.
	 * To be called by resource management code when preparing a newly
	 * created resource (for example, a JDBC Connection).
	 * @return the currently exposed isolation level, according to the
	 * JDBC Connection constants (equivalent to the corresponding Spring
	 * TransactionDefinition constants), or <code>null</code> if none
	 * @see java.sql.Connection#TRANSACTION_READ_UNCOMMITTED
	 * @see java.sql.Connection#TRANSACTION_READ_COMMITTED
	 * @see java.sql.Connection#TRANSACTION_REPEATABLE_READ
	 * @see java.sql.Connection#TRANSACTION_SERIALIZABLE
	 * @see org.springframework.transaction.TransactionDefinition#ISOLATION_READ_UNCOMMITTED
	 * @see org.springframework.transaction.TransactionDefinition#ISOLATION_READ_COMMITTED
	 * @see org.springframework.transaction.TransactionDefinition#ISOLATION_REPEATABLE_READ
	 * @see org.springframework.transaction.TransactionDefinition#ISOLATION_SERIALIZABLE
	 * @see org.springframework.transaction.TransactionDefinition#getIsolationLevel()
	 */
	public static Integer getCurrentTransactionIsolationLevel() {
		return (Integer) currentTransactionIsolationLevel.get();
	}

	/**
	 * Expose whether there currently is an actual transaction active.
	 * Called by the transaction manager on transaction begin and on cleanup.
	 * @param active <code>true</code> to mark the current thread as being associated
	 * with an actual transaction; <code>false</code> to reset that marker
	 */
	public static void setActualTransactionActive(boolean active) {
		actualTransactionActive.set(active ? Boolean.TRUE : null);
	}

	/**
	 * Return whether there currently is an actual transaction active.
	 * This indicates whether the current thread is associated with an actual
	 * transaction rather than just with active transaction synchronization.
	 * <p>To be called by resource management code that wants to discriminate
	 * between active transaction synchronization (with or without backing
	 * resource transaction; also on PROPAGATION_SUPPORTS) and an actual
	 * transaction being active (with backing resource transaction;
	 * on PROPAGATION_REQUIRES, PROPAGATION_REQUIRES_NEW, etc).
	 * @see #isSynchronizationActive()
	 */
	public static boolean isActualTransactionActive() {
		return (actualTransactionActive.get() != null);
	}


	/**
	 * Clear the entire transaction synchronization state for the current thread:
	 * registered synchronizations as well as the various transaction characteristics.
	 * @see #clearSynchronization()
	 * @see #setCurrentTransactionName
	 * @see #setCurrentTransactionReadOnly
	 * @see #setCurrentTransactionIsolationLevel
	 * @see #setActualTransactionActive
	 */
	public static void clear() {
		clearSynchronization();
		setCurrentTransactionName(null);
		setCurrentTransactionReadOnly(false);
		setCurrentTransactionIsolationLevel(null);
		setActualTransactionActive(false);
	}

}
 

 

我们发现这个类里面有很多的ThreadLocal 对象,关于TreadLocal的作用这里不做解释,不懂的可以上网查阅;

简言之  :TreadLocal就是线程局部变量,在整个线程存活期间,可以随时访问该变量,当线程死亡自后,该变量也会随着线程一起死亡,最后由被GC回收。所以我们的sessionHolder是和线程绑定在一起的,所以在线程存活期间,可以随时得到这个sessionHolder,进而取得数据库的session。

 

 

 

接下来,我们看看 public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException 的doBegin(transaction, definition);

他也是个抽象函数,也是在子类里面实现 我们来看看Hibernate的的这个实现方法

 

 

 

protected void doBegin(Object transaction, TransactionDefinition definition) {
		HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;

		if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
			throw new IllegalTransactionStateException(
					"Pre-bound JDBC Connection found! HibernateTransactionManager does not support " +
					"running within DataSourceTransactionManager if told to manage the DataSource itself. " +
					"It is recommended to use a single HibernateTransactionManager for all transactions " +
					"on a single DataSource, no matter whether Hibernate or JDBC access.");
		}

		Session session = null;

		try {
			if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
				Interceptor entityInterceptor = getEntityInterceptor();
				Session newSession = (entityInterceptor != null ?
						getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession());
				if (logger.isDebugEnabled()) {
					logger.debug("Opened new Session [" + SessionFactoryUtils.toString(newSession) +
							"] for Hibernate transaction");
				}
				txObject.setSession(newSession);
			}

			session = txObject.getSessionHolder().getSession();

			if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
				// We're allowed to change the transaction settings of the JDBC Connection.
				if (logger.isDebugEnabled()) {
					logger.debug(
							"Preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]");
				}
				Connection con = session.connection();
				Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
				txObject.setPreviousIsolationLevel(previousIsolationLevel);
			}
			else {
				// Not allowed to change the transaction settings of the JDBC Connection.
				if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
					// We should set a specific isolation level but are not allowed to...
					throw new InvalidIsolationLevelException(
							"HibernateTransactionManager is not allowed to support custom isolation levels: " +
							"make sure that its 'prepareConnection' flag is on (the default) and that the " +
							"Hibernate connection release mode is set to 'on_close' (SpringTransactionFactory's default). " +
							"Make sure that your LocalSessionFactoryBean actually uses SpringTransactionFactory: Your " +
							"Hibernate properties should *not* include a 'hibernate.transaction.factory_class' property!");
				}
				if (logger.isDebugEnabled()) {
					logger.debug(
							"Not preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]");
				}
			}

			if (definition.isReadOnly() && txObject.isNewSession()) {
				// Just set to NEVER in case of a new Session for this transaction.
				session.setFlushMode(FlushMode.NEVER);
			}

			if (!definition.isReadOnly() && !txObject.isNewSession()) {
				// We need AUTO or COMMIT for a non-read-only transaction.
				FlushMode flushMode = session.getFlushMode();
				if (flushMode.lessThan(FlushMode.COMMIT)) {
					session.setFlushMode(FlushMode.AUTO);
					txObject.getSessionHolder().setPreviousFlushMode(flushMode);
				}
			}

			Transaction hibTx = null;

			// Register transaction timeout.
			int timeout = determineTimeout(definition);
			if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
				// Use Hibernate's own transaction timeout mechanism on Hibernate 3.1
				// Applies to all statements, also to inserts, updates and deletes!
				hibTx = session.getTransaction();
				hibTx.setTimeout(timeout);
				hibTx.begin();
			}
			else {
				// Open a plain Hibernate transaction without specified timeout.
				hibTx = session.beginTransaction();
			}

			// Add the Hibernate transaction to the session holder.
			txObject.getSessionHolder().setTransaction(hibTx);

			// Register the Hibernate Session's JDBC Connection for the DataSource, if set.
			if (getDataSource() != null) {
				Connection con = session.connection();
				ConnectionHolder conHolder = new ConnectionHolder(con);
				if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
					conHolder.setTimeoutInSeconds(timeout);
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Exposing Hibernate transaction as JDBC transaction [" + con + "]");
				}
				TransactionSynchronizationManager.bindResource(getDataSource(), conHolder);
				txObject.setConnectionHolder(conHolder);
			}

			// Bind the session holder to the thread.
			if (txObject.isNewSessionHolder()) {
				TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder());
			}
			txObject.getSessionHolder().setSynchronizedWithTransaction(true);
		}

		catch (Exception ex) {
			if (txObject.isNewSession()) {
				try {
					if (session.getTransaction().isActive()) {
						session.getTransaction().rollback();
					}
				}
				catch (Throwable ex2) {
					logger.debug("Could not rollback Session after failed transaction begin", ex);
				}
				finally {
					SessionFactoryUtils.closeSession(session);
				}
			}
			throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex);
		}
	}

 

 

这个方法里面是从sessionHolder中获取session 然后hibTx = session.getTransaction();

hibTx.setTimeout(timeout);

hibTx.begin();

 

我觉得如果你对Hibernate的事物很熟悉,我想不用解释你就可以了解这是干什么,这个上就是获取Hibernate的自身的事物Transaction。到此,事物开始;

 

我们在看看事物的提交  

 

 

ransactionManager .commit(status );

 

 

 

/**
	 * This implementation of commit handles participating in existing
	 * transactions and programmatic rollback requests.
	 * Delegates to <code>isRollbackOnly</code>, <code>doCommit</code>
	 * and <code>rollback</code>.
	 * @see org.springframework.transaction.TransactionStatus#isRollbackOnly()
	 * @see #doCommit
	 * @see #rollback
	 */
	public final void commit(TransactionStatus status) throws TransactionException {
		if (status.isCompleted()) {
			throw new IllegalTransactionStateException(
					"Transaction is already completed - do not call commit or rollback more than once per transaction");
		}

		DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
		if (defStatus.isLocalRollbackOnly()) {
			if (defStatus.isDebug()) {
				logger.debug("Transactional code has requested rollback");
			}
			processRollback(defStatus);
			return;
		}
		if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
			if (defStatus.isDebug()) {
				logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
			}
			processRollback(defStatus);
			// Throw UnexpectedRollbackException only at outermost transaction boundary
			// or if explicitly asked to.
			if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
				throw new UnexpectedRollbackException(
						"Transaction rolled back because it has been marked as rollback-only");
			}
			return;
		}

		processCommit(defStatus);
	}

我们看到一句processCommit(defStatus)

 

 

	/**
	 * Process an actual commit.
	 * Rollback-only flags have already been checked and applied.
	 * @param status object representing the transaction
	 * @throws TransactionException in case of commit failure
	 */
	private void processCommit(DefaultTransactionStatus status) throws TransactionException {
		try {
			boolean beforeCompletionInvoked = false;
			try {
				prepareForCommit(status);
				triggerBeforeCommit(status);
				triggerBeforeCompletion(status);
				beforeCompletionInvoked = true;
				boolean globalRollbackOnly = false;
				if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
					globalRollbackOnly = status.isGlobalRollbackOnly();
				}
				if (status.hasSavepoint()) {
					if (status.isDebug()) {
						logger.debug("Releasing transaction savepoint");
					}
					status.releaseHeldSavepoint();
				}
				else if (status.isNewTransaction()) {
					if (status.isDebug()) {
						logger.debug("Initiating transaction commit");
					}
					doCommit(status);
				}
				// Throw UnexpectedRollbackException if we have a global rollback-only
				// marker but still didn't get a corresponding exception from commit.
				if (globalRollbackOnly) {
					throw new UnexpectedRollbackException(
							"Transaction silently rolled back because it has been marked as rollback-only");
				}
			}
			catch (UnexpectedRollbackException ex) {
				// can only be caused by doCommit
				triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
				throw ex;
			}
			catch (TransactionException ex) {
				// can only be caused by doCommit
				if (isRollbackOnCommitFailure()) {
					doRollbackOnCommitException(status, ex);
				}
				else {
					triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
				}
				throw ex;
			}
			catch (RuntimeException ex) {
				if (!beforeCompletionInvoked) {
					triggerBeforeCompletion(status);
				}
				doRollbackOnCommitException(status, ex);
				throw ex;
			}
			catch (Error err) {
				if (!beforeCompletionInvoked) {
					triggerBeforeCompletion(status);
				}
				doRollbackOnCommitException(status, err);
				throw err;
			}

			// Trigger afterCommit callbacks, with an exception thrown there
			// propagated to callers but the transaction still considered as committed.
			try {
				triggerAfterCommit(status);
			}
			finally {
				triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
			}

		}
		finally {
			cleanupAfterCompletion(status);
		}
	}

 

看到doCommit(status); 方法没有,这个方法也是在子类里面实现的我们来看看hibernate里面的具体实现

 

 

	protected void doCommit(DefaultTransactionStatus status) {
		HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
		if (status.isDebug()) {
			logger.debug("Committing Hibernate transaction on Session [" +
					SessionFactoryUtils.toString(txObject.getSessionHolder().getSession()) + "]");
		}
		try {
			txObject.getSessionHolder().getTransaction().commit();
		}
		catch (org.hibernate.TransactionException ex) {
			// assumably from commit call to the underlying JDBC connection
			throw new TransactionSystemException("Could not commit Hibernate transaction", ex);
		}
		catch (HibernateException ex) {
			// assumably failed to flush changes to database
			throw convertHibernateAccessException(ex);
		}
	}
 

看到 txObject.getSessionHolder().getTransaction().commit(); 我们就明白了

 

而rollback是在 protected void doRollback(DefaultTransactionStatus status) {

		HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
		if (status.isDebug()) {
			logger.debug("Rolling back Hibernate transaction on Session [" +
					SessionFactoryUtils.toString(txObject.getSessionHolder().getSession()) + "]");
		}
		try {
			txObject.getSessionHolder().getTransaction().rollback();
		}
		catch (org.hibernate.TransactionException 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.isNewSession() && !this.hibernateManagedSession) {
				// Clear all pending inserts/updates/deletes in the Session.
				// Necessary for pre-bound Sessions, to avoid inconsistent state.
				txObject.getSessionHolder().getSession().clear();
			}
		}
	}
 

这个方法里面实现的  

 

txObject.getSessionHolder().getTransaction().rollback();

 

spring其实最终调用的hibernate的本事事物管理来进行事物的提交和回滚的,其实类型的事物都是按照这个模板来写的例如   jdbc  ,jdo 等等

分享到:
评论

相关推荐

    spring 1.2源代码

    Spring 1.2源代码是Java开发者深入了解Spring框架工作原理的重要资源。这个版本的Spring框架在2004年发布,标志着Spring框架发展的早期阶段,它包含了许多核心特性,为现代企业级Java应用奠定了基础。在这个源代码...

    Spring3.0源代码

    通过对Spring3.0.5源代码的深入研究,开发者可以更好地理解其工作原理,从而优化自己的代码,提升应用程序的性能和稳定性。同时,这也是学习设计模式和最佳实践的好机会,因为Spring框架本身就是一个优秀的示例,...

    springTransaction.rar

    "springTransaction"这个文件可能是项目的源代码,其中包含了转账业务逻辑的实现。在这个示例中,可能会有若干个带有@Transactional注解的方法,比如`transferMoney()`,它会调用两个数据库操作,分别对应于扣款和...

    spring2.5.6源代码及api

    在这里,我们将深入探讨Spring 2.5.6源代码和API中的一些重要知识点。 1. **依赖注入(Dependency Injection, DI)**:Spring的核心特性之一就是依赖注入,它允许开发者通过配置文件或注解来管理对象之间的依赖关系...

    spring-note spring 读书笔记

    `spring_transaction.txt`会详细阐述如何配置事务管理,以及@Transactional注解的使用。 7. **Spring安全(Spring Security)**: `spring_security.sql`和`spring_security.txt`可能涉及到Spring Security的基本...

    spring-transaction.jar.zip

    "spring-transaction.jar"正是提供了Spring事务管理的类库,它包含了一系列用于处理事务的接口、类和配置元素,使得开发者能够方便地实现事务控制。 一、Spring 事务管理概述 Spring事务管理分为编程式事务管理和...

    Spring源代码(spring.zip)

    在源代码中,`org.springframework.beans` 和 `org.springframework.context` 包含了关于IoC容器的主要实现,如`BeanFactory`和`ApplicationContext`接口,它们提供了配置和管理bean的能力。 2. **依赖注入**:...

    Spring 常用 Transaction Annotation

    本篇主要聚焦于"Spring 常用 Transaction Annotation",即声明式事务管理,这是一种更简洁、易于维护的事务控制方式。 首先,Spring的声明式事务管理基于AOP(面向切面编程),它允许我们在不修改业务代码的情况下...

    spring源代码包

    源代码是理解任何软件系统内部运作的关键,对于Spring框架而言,通过阅读源码,我们可以深入理解其设计理念和实现机制。 在Spring框架的源代码中,有几个关键部分值得我们关注: 1. **IoC容器**:这是Spring的核心...

    Spring整合Mybatis源代码

    在Spring配置文件中,我们需要配置数据源、MyBatis的配置文件路径以及映射文件的位置。 ```xml &lt;bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt; ...

    Spring框架核心源代码的分析及其感受-6

    在源代码中,`org.springframework.transaction.interceptor`包下的类实现了事务的切面处理。 总的来说,深入分析Spring框架的源代码,能够帮助我们理解其设计思想和实现原理,从而在实际开发中更好地利用这些功能...

    Spring攻略(第三版)源代码

    12. Spring Transaction Management 13. Spring Batch 14. Spring NoSQL and Big Data 15. Spring Java Enterprise Services and Remoting Technologies 16. Spring Messaging 17. Spring Integration 18. Spring ...

    spring源代码

    相关代码位于`org.springframework.transaction`包下。 Spring还提供了数据访问抽象,包括JDBC、ORM(Object-Relational Mapping)和OXM(Object-XML Mapping)。例如,`JdbcTemplate`和`SimpleJdbcInsert`使得JDBC...

    Spring在Transaction事务传播行为种类

    ### Spring中的Transaction事务传播行为种类详解 #### 一、引言 在开发基于Spring框架的应用程序时,事务管理是确保数据一致性的重要手段之一。Spring框架提供了丰富的事务管理功能,其中包括了事务传播行为...

    springtransaction 事务管理

    在实际项目中,`springtransaction`工程可能是包含了一个完整的示例,用于演示如何在MyEclipse环境中配置和使用Spring的事务管理功能。开发者可以通过导入此工程,学习和实践Spring事务管理的配置与使用,从而更好地...

    spring-framework-3.2.5.RELEASE 源代码

    《Spring Framework 3.2.5.RELEASE 源代码深度解析》 Spring Framework作为Java领域最广泛应用的轻量级框架之一,其3.2.5.RELEASE版本的源代码蕴含了丰富的设计思想和技术实现。深入理解这个版本的源代码,不仅可以...

    org.springframework.transaction-3.2.2.RELEASE

    org.springframework.transaction-3.2.2.RELEASE最新版本

    j2ee 源代码 集合

    `javaee-core.jar`可能包含了J2EE核心库的部分源代码或类库,这些库提供了诸如EJB(Enterprise JavaBeans)、JMS(Java Message Service)、JTA(Java Transaction API)等关键服务的接口和实现。通过查看这些源代码...

    spring 2.5 source code, java源代码

    在深入研究Spring 2.5的源代码之前,我们需要理解Spring的核心概念和架构。 1. **依赖注入(Dependency Injection, DI)**:Spring的核心特性之一是依赖注入,它允许对象在运行时通过容器进行装配,而不是在代码...

    spring笔记

    Spring笔记中提到的技术知识点主要围绕Hibernate框架展开,Hibernate是一个开放源代码的对象关系映射(Object/Relational Mapping,简称ORM)框架,用于Java环境。它对JDBC进行了非常轻量级的对象封装,使得开发者...

Global site tag (gtag.js) - Google Analytics