⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jtatransactionmanager.java

📁 spring的源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright 2002-2004 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 

package org.springframework.transaction.jta;

import javax.naming.NamingException;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.InvalidTransactionException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.jndi.JndiTemplate;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.HeuristicCompletionException;
import org.springframework.transaction.IllegalTransactionStateException;
import org.springframework.transaction.InvalidIsolationLevelException;
import org.springframework.transaction.NoTransactionException;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.transaction.UnexpectedRollbackException;
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
import org.springframework.transaction.support.DefaultTransactionStatus;

/**
 * PlatformTransactionManager implementation for JTA, i.e. J2EE container transactions.
 * Can also work with a locally configured JTA implementation.
 *
 * <p>This transaction manager is appropriate for handling distributed transactions,
 * i.e. transactions that span multiple resources, and for managing transactions
 * on a J2EE Connector (e.g. a persistence toolkit registered as JCA Connector).
 * For a single JDBC DataSource, DataSourceTransactionManager is perfectly sufficient,
 * and for accessing a single resource with Hibernate (including transactional cache),
 * HibernateTransactionManager is appropriate.
 *
 * <p>Transaction synchronization is active by default, to allow data access support
 * classes to register resources that are opened within the transaction for closing at
 * transaction completion time. Spring's support classes for JDBC, Hibernate and JDO
 * all perform such registration, allowing for reuse of the same Hibernate Session etc
 * within the transaction. Standard JTA does not even guarantee that for Connections
 * from a transactional JDBC DataSource: Spring's synchronization solves those issues.
 *
 * <p>Synchronization is also leveraged for transactional cache handling with Hibernate.
 * Therefore, as long as JtaTransactionManager drives the JTA transactions, there is
 * no need to configure Hibernate's JTATransaction strategy or a container-specific
 * Hibernate TransactionManagerLookup. However, certain JTA implementations are
 * restrictive in terms of what JDBC calls they allow after transaction completion,
 * complaining even on close calls: In that case, it is indeed necessary to configure
 * a Hibernate TransactionManagerLookup; Spring will automatically adapt to this.
 *
 * <p>If JtaTransactionManager participates in an existing JTA transaction, e.g. from
 * EJB CMT, synchronization will be triggered on finishing the nested transaction,
 * before passing transaction control back to the J2EE container. In this case, a
 * container-specific Hibernate TransactionManagerLookup is the only way to achieve
 * exact afterCompletion callbacks for transactional cache handling with Hibernate.
 * In such a scenario, use Hibernate >=2.1 which features automatic JTA detection.
 *
 * <p>Transaction suspension (REQUIRES_NEW, NOT_SUPPORTED) is just available with
 * a JTA TransactionManager being registered, via the "transactionManagerName" or
 * "transactionManager" property. The location of this internal JTA object is
 * <i>not</i> specified by J2EE; it is individual for each J2EE server, often kept
 * in JNDI like the UserTransaction. Some well-known JNDI locations are:
 * <ul>
 * <li>"java:comp/UserTransaction" for Resin, Orion, JOnAS (JOTM)
 * <li>"java:/TransactionManager" for JBoss, JRun4
 * <li>"javax.transaction.TransactionManager" for BEA WebLogic
 * </ul>
 *
 * <p>"java:comp/UserTransaction" as JNDI name for the TransactionManager means that
 * the same JTA object implements both the UserTransaction and the TransactionManager
 * interface. As this is easy to test when looking up the UserTransaction, this will
 * be auto-detected on initialization of JtaTransactionManager. Thus, there's no need
 * to specify the "transactionManagerName" in this case (for Resin, Orion, JOnAS).
 *
 * <p>For IBM WebSphere and standalone JOTM, static accessor methods are required to
 * obtain the JTA TransactionManager: Therefore, WebSphere and JOTM have their own
 * FactoryBean implementations, to be wired with the "transactionManager" property.
 * In case of JotmFactoryBean, the same JTA object implements UserTransaction too:
 * Therefore, passing the object to the "userTransaction" property is sufficient.
 *
 * <p>The internal JTA TransactionManager can also be used to register custom
 * synchronizations with the JTA transaction itself instead of Spring's
 * transaction manager. LocalSessionFactoryBean supports plugging a given
 * TransactionManager into Hibernate's TransactionManagerLookup mechanism,
 * for Hibernate-driven cache synchronization without double configuration.
 *
 * <p>JtaTransactionManager supports timeouts but not custom isolation levels.
 * Custom subclasses can override applyIsolationLevel for specific JTA
 * implementations. Note that some resource-specific transaction managers like
 * DataSourceTransactionManager and HibernateTransactionManager do support timeouts,
 * custom isolation levels, and transaction suspension without JTA's restrictions.
 *
 * @author Juergen Hoeller
 * @since 24.03.2003
 * @see #setUserTransactionName
 * @see #setTransactionManagerName
 * @see #applyIsolationLevel
 * @see JotmFactoryBean
 * @see WebSphereTransactionManagerFactoryBean
 * @see org.springframework.orm.hibernate.LocalSessionFactoryBean#setJtaTransactionManager
 * @see org.springframework.orm.hibernate.HibernateTransactionManager
 * @see org.springframework.jdbc.datasource.DataSourceTransactionManager
 */
public class JtaTransactionManager extends AbstractPlatformTransactionManager implements InitializingBean {

	public static final String DEFAULT_USER_TRANSACTION_NAME = "java:comp/UserTransaction";

	private JndiTemplate jndiTemplate = new JndiTemplate();

	private UserTransaction userTransaction;

	private String userTransactionName = DEFAULT_USER_TRANSACTION_NAME;

	private TransactionManager transactionManager;

	private String transactionManagerName;


	/**
	 * Set the JndiTemplate to use for JNDI lookups.
	 * A default one is used if not set.
	 */
	public void setJndiTemplate(JndiTemplate jndiTemplate) {
		if (jndiTemplate == null) {
			throw new IllegalArgumentException("jndiTemplate must not be null");
		}
		this.jndiTemplate = jndiTemplate;
	}

	/**
	 * Set the JTA UserTransaction to use as direct reference.
	 * Typically just used for local JTA setups; in a J2EE environment,
	 * the UserTransaction will always be fetched from JNDI.
	 */
	public void setUserTransaction(UserTransaction userTransaction) {
		this.userTransaction = userTransaction;
	}

	/**
	 * Set the JNDI name of the JTA UserTransaction.
	 * The default one is used if not set.
	 * @see #DEFAULT_USER_TRANSACTION_NAME
	 */
	public void setUserTransactionName(String userTransactionName) {
		this.userTransactionName = userTransactionName;
	}

	/**
	 * Set the JTA TransactionManager to use as direct reference.
	 * <p>A TransactionManager is necessary for suspending and resuming transactions,
	 * as this not supported by the UserTransaction interface.
	 */
	public void setTransactionManager(TransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}

	/**
	 * Set the JNDI name of the JTA TransactionManager.
	 * <p>A TransactionManager is necessary for suspending and resuming transactions,
	 * as this not supported by the UserTransaction interface.
	 */
	public void setTransactionManagerName(String transactionManagerName) {
		this.transactionManagerName = transactionManagerName;
	}


	public void afterPropertiesSet() throws CannotCreateTransactionException {
		if (this.userTransaction == null) {
			if (this.userTransactionName != null) {
				this.userTransaction = lookupUserTransaction(this.userTransactionName);
			}
			else {
				throw new IllegalArgumentException("Either userTransaction or userTransactionName must be set");
			}
		}
		if (this.transactionManager == null) {
			if (this.transactionManagerName != null) {
				this.transactionManager = lookupTransactionManager(this.transactionManagerName);
			}
			else if (this.userTransaction instanceof TransactionManager) {
				if (logger.isInfoEnabled()) {
					logger.info("JTA UserTransaction object [" + this.userTransaction + "] implements TransactionManager");
				}
				this.transactionManager = (TransactionManager) this.userTransaction;
			}
			else {
				logger.info("No JTA TransactionManager specified - transaction suspension not available");
			}
		}
	}

	/**

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -