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

📄 toplinktransactionmanager.java

📁 spring的源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright 2002-2005 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.orm.toplink;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import oracle.toplink.exceptions.DatabaseException;
import oracle.toplink.exceptions.TopLinkException;
import oracle.toplink.internal.databaseaccess.Accessor;
import oracle.toplink.internal.databaseaccess.DatabaseAccessor;
import oracle.toplink.sessions.Session;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.datasource.ConnectionHolder;
import org.springframework.jdbc.datasource.JdbcTransactionObjectSupport;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
import org.springframework.jdbc.support.SQLExceptionTranslator;
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
import org.springframework.transaction.support.DefaultTransactionStatus;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * <p>PlatformTransactionManager implementation for a single TopLink SessionFactory.
 * Binds a TopLink Session from the specified factory to the thread, potentially
 * allowing for one thread Session per factory. SessionFactoryUtils and TopLinkTemplate
 * are aware of thread-bound Sessions and participate in such transactions automatically.
 * Using either of those or going through <code>Session.getActiveUnitOfWork()</code> is
 * required for TopLink access code that needs to support this transaction handling mechanism.
 *
 * <p>This implementation is appropriate for applications that solely use TopLink for
 * transactional data access. JTA (usually through JtaTransactionManager) is necessary for
 * accessing multiple transactional resources. Note that you need to configure TopLink with
 * an appropriate external transaction controller, to make it participate in JTA transactions.
 * In contrast to Hibernate, this cannot be transparently provided by the Spring transaction
 * manager implementation.
 *
 * <p>This implementation also supports direct DataSource access within a transaction
 * (i.e. plain JDBC code working with the same DataSource), but only for transactions that
 * are <i>not</i> marked as read-only. This allows for mixing services that access TopLink
 * (including transactional caching) and services that use plain JDBC (without being aware
 * of TopLink)! Application code needs to stick to the same simple Connection lookup pattern
 * with DataSourceTransactionManager (i.e. <code>DataSourceUtils.getConnection</code>
 * or going through a TransactionAwareDataSourceProxy).
 *
 * <p>Note that to be able to register a DataSource's Connection for plain JDBC code,
 * this instance needs to be aware of the DataSource (see "dataSource" property).
 * The given DataSource should obviously match the one used by the given TopLink
 * SessionFactory.
 *
 * <p>On JDBC 3.0, this transaction manager supports nested transactions via JDBC
 * 3.0 Savepoints. The "nestedTransactionAllowed" flag defaults to "false", though,
 * as nested transactions will just apply to the JDBC Connection, not to the
 * TopLink Session and its cached objects. You can manually set the flag to "true"
 * if you want to use nested transactions for JDBC access code that participates
 * in TopLink transactions (provided that your JDBC driver supports Savepoints).
 * <i>Note that TopLink itself does not support nested transactions! Hence,
 * do not expect TopLink access code to participate in a nested transaction.</i>
 *
 * <p>Thanks to Slavik Markovich for implementing the initial TopLink support prototype!
 *
 * @author Juergen Hoeller
 * @author <a href="mailto:james.x.clark@oracle.com">James Clark</a>
 * @since 1.2
 * @see #setSessionFactory
 * @see #setDataSource
 * @see LocalSessionFactoryBean
 * @see SessionFactoryUtils#getSession
 * @see SessionFactoryUtils#releaseSession
 * @see TopLinkTemplate
 * @see oracle.toplink.sessions.Session#getActiveUnitOfWork()
 * @see org.springframework.jdbc.datasource.DataSourceUtils#getConnection
 * @see org.springframework.jdbc.datasource.DataSourceUtils#applyTransactionTimeout
 * @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection
 * @see org.springframework.jdbc.core.JdbcTemplate
 * @see org.springframework.jdbc.datasource.DataSourceTransactionManager
  * @see org.springframework.transaction.jta.JtaTransactionManager
 */
public class TopLinkTransactionManager extends AbstractPlatformTransactionManager implements InitializingBean {

	private SessionFactory sessionFactory;

	private DataSource dataSource;

	private boolean lazyDatabaseTransaction = false;

	private SQLExceptionTranslator jdbcExceptionTranslator;


	/**
	 * Create a new TopLinkTransactionManager instance.
	 * A SessionFactory has to be specified to be able to use it.
	 * @see #setSessionFactory
	 */
	public TopLinkTransactionManager() {
	}

	/**
	 * Create a new TopLinkTransactionManager instance.
	 * @param sessionFactory the TopLink SessionFactory to manage transactions for
	 */
	public TopLinkTransactionManager(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
		afterPropertiesSet();
	}

	/**
	 * Set the the TopLink SessionFactory to manage transactions for.
	 * This will usually be a ServerSessionFactory.
	 * <p>The passed-in SessionFactory will be asked for a plain Session
	 * in case of a read-only transaction (where no active UnitOfWork is
	 * supposed to be available), and for a managed Session else (with an
	 * active UnitOfWork that will be committed by this transaction manager).
	 * @see ServerSessionFactory
	 * @see SessionFactory#createSession()
	 * @see SessionFactory#createManagedClientSession()
	 */
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	/**
	 * Return the SessionFactory that this instance should manage transactions for.
	 */
	public SessionFactory getSessionFactory() {
		return this.sessionFactory;
	}

	/**
	 * Set the JDBC DataSource that this instance should manage transactions for.
   * The DataSource should match the one used by the TopLink SessionFactory:
	 * for example, you could specify the same JNDI DataSource for both.
	 * <p>A transactional JDBC Connection for this DataSource will be provided to
	 * application code accessing this DataSource directly via DataSourceUtils
	 * or JdbcTemplate. The Connection will be taken from the TopLink Session.
	 * <b>This will only happen for transactions that are <i>not</i> marked
	 * as read-only.</b> TopLink does not support database transactions for pure
	 * read-only operations on a Session (that is, without a UnitOfWork).
	 * <p>Note that you need to use a TopLink Session with a DatabaseAccessor
	 * to allow for exposing TopLink transactions as JDBC transactions. This is
	 * the case of all standard TopLink configurations.
	 * <p>The DataSource specified here should be the target DataSource to manage
	 * transactions for, not a TransactionAwareDataSourceProxy. Only data access
	 * code may work with TransactionAwareDataSourceProxy, while the transaction
	 * manager needs to work on the underlying target DataSource. If there's
	 * nevertheless a TransactionAwareDataSourceProxy passed in, it will be
	 * unwrapped to extract its target DataSource.
	 * @see org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy
	 * @see org.springframework.jdbc.datasource.DataSourceUtils
	 * @see org.springframework.jdbc.core.JdbcTemplate
	 */
	public void setDataSource(DataSource dataSource) {
		if (dataSource instanceof TransactionAwareDataSourceProxy) {
			// If we got a TransactionAwareDataSourceProxy, we need to perform transactions
			// for its underlying target DataSource, else data access code won't see
			// properly exposed transactions (i.e. transactions for the target DataSource).
			this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource();
		}
		else {
			this.dataSource = dataSource;
		}
	}

	/**
	 * Return the JDBC DataSource that this instance manages transactions for.
	 */
	public DataSource getDataSource() {
		return dataSource;
	}

	/**
	 * Set whether to lazily start a database transaction within a TopLink
	 * transaction.
	 * <p>By default, database transactions are started early. This allows
	 * for reusing the same JDBC Connection throughout an entire transaction,
	 * including read operations, and also for exposing TopLink transactions
	 * to JDBC access code (working on the same DataSource).
	 * <p>It is only recommended to switch this flag to "true" when no JDBC access
	 * code is involved in any of the transactions, and when it is acceptable to
	 * perform read operations outside of the transactional JDBC Connection.
	 * @see #setDataSource(javax.sql.DataSource)
	 * @see oracle.toplink.sessions.UnitOfWork#beginEarlyTransaction()
	 */
	public void setLazyDatabaseTransaction(boolean lazyDatabaseTransaction) {
		this.lazyDatabaseTransaction = lazyDatabaseTransaction;
	}

	/**
	 * Return whether to lazily start a database transaction within a TopLink
	 * transaction.
	 */
	public boolean isLazyDatabaseTransaction() {
		return lazyDatabaseTransaction;
	}

	/**
	 * Set the JDBC exception translator for this instance.
	 * Applied to TopLink DatabaseExceptions thrown on commit.
	 * <p>The default exception translator is either a SQLErrorCodeSQLExceptionTranslator
	 * if a DataSource is available, or a SQLStateSQLExceptionTranslator else.
	 * @param jdbcExceptionTranslator the exception translator
	 * @see oracle.toplink.exceptions.DatabaseException
	 * @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
	 * @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
	 * @see #setDataSource(javax.sql.DataSource)
	 */
	public void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator) {
		this.jdbcExceptionTranslator = jdbcExceptionTranslator;
	}

	/**
	 * Return the JDBC exception translator for this transaction manager.
	 * <p>Creates a default SQLErrorCodeSQLExceptionTranslator or SQLStateSQLExceptionTranslator
	 * for the specified SessionFactory, if no exception translator explicitly specified.
	 * @see #setJdbcExceptionTranslator
	 */
	public SQLExceptionTranslator getJdbcExceptionTranslator() {
		if (this.jdbcExceptionTranslator == null) {
			if (getDataSource() != null) {
				this.jdbcExceptionTranslator = new SQLErrorCodeSQLExceptionTranslator(getDataSource());
			}
			else {
				this.jdbcExceptionTranslator = new SQLStateSQLExceptionTranslator();
			}
		}
		return this.jdbcExceptionTranslator;
	}

⌨️ 快捷键说明

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