SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
if (holder != null && holder.isSynchronizedWithTransaction()) {
if (holder.getExecutorType() != executorType) {
throw new TransientDataAccessResourceException(
"Cannot change the ExecutorType when there is an existing transaction");
}
holder.requested();
if (logger.isDebugEnabled()) {
logger.debug("Fetched SqlSession [" + holder.getSqlSession() + "] from current transaction");
}
return holder.getSqlSession();
}
DataSource dataSource = sessionFactory.getConfiguration().getEnvironment().getDataSource();
// SqlSessionFactoryBean unwraps TransactionAwareDataSourceProxies but
// we keep this check for the case that SqlSessionUtils is called from custom code
boolean transactionAware = (dataSource instanceof TransactionAwareDataSourceProxy);
Connection conn;
try {
conn = transactionAware ? dataSource.getConnection() : DataSourceUtils.getConnection(dataSource);
} catch (SQLException e) {
throw new CannotGetJdbcConnectionException("Could not get JDBC Connection for SqlSession", e);
}
if (logger.isDebugEnabled()) {
logger.debug("Creating SqlSession with JDBC Connection [" + conn + "]");
}
// Assume either DataSourceTransactionManager or the underlying
// connection pool already dealt with enabling auto commit.
// This may not be a good assumption, but the overhead of checking
// connection.getAutoCommit() again may be expensive (?) in some drivers
// (see DataSourceTransactionManager.doBegin()). One option would be to
// only check for auto commit if this function is being called outside
// of DSTxMgr, but to do that we would need to be able to call
// ConnectionHolder.isTransactionActive(), which is protected and not
// visible to this class.
SqlSession session = sessionFactory.openSession(executorType, conn);
// Register session holder and bind it to enable synchronization.
//
// Note: The DataSource should be synchronized with the transaction
// either through DataSourceTxMgr or another tx synchronization.
// Further assume that if an exception is thrown, whatever started the transaction will
// handle closing / rolling back the Connection associated with the SqlSession.
if (TransactionSynchronizationManager.isSynchronizationActive()) {
if (!(sessionFactory.getConfiguration().getEnvironment().getTransactionFactory() instanceof SpringManagedTransactionFactory)
&& DataSourceUtils.isConnectionTransactional(conn, dataSource)) {
throw new TransientDataAccessResourceException(
"SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization");
}
if (logger.isDebugEnabled()) {
logger.debug("Registering transaction synchronization for SqlSession [" + session + "]");