/** * Prepare the given Connection with the given transaction semantics. * * @param con the Connection to prepare * @param definition the transaction definition to apply * @return the previous isolation level, if any * @throws SQLException if thrown by JDBC methods * @see #resetConnectionAfterTransaction */ public static Integer prepareConnectionForTransaction( Connection con, TransactionDefinition definition) throws SQLException { Assert.notNull(con, "No Connection specified"); // Set read-only flag. if (definition != null && definition.isReadOnly()) { try { if (logger.isDebugEnabled()) { logger.debug("Setting JDBC Connection [" + con + "] read-only"); } con.setReadOnly(true); } catch (Throwable ex) { // SQLException or UnsupportedOperationException // -> ignore, it's just a hint anyway. logger.debug("Could not set JDBC Connection read-only", ex); } } // Apply specific isolation level, if any. Integer previousIsolationLevel = null; if (definition != null && definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { if (logger.isDebugEnabled()) { logger.debug( "Changing isolation level of JDBC Connection [" + con + "] to " + definition.getIsolationLevel()); } previousIsolationLevel = con.getTransactionIsolation(); con.setTransactionIsolation(definition.getIsolationLevel()); } return previousIsolationLevel; }
@Override protected void doBegin(Object transaction, TransactionDefinition definition) { JpaTransactionObject txObject = (JpaTransactionObject) transaction; if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) { throw new IllegalTransactionStateException( "Pre-bound JDBC Connection found! JpaTransactionManager does not support " + "running within DataSourceTransactionManager if told to manage the DataSource itself. " + "It is recommended to use a single JpaTransactionManager for all transactions " + "on a single DataSource, no matter whether JPA or JDBC access."); } try { if (txObject.getEntityManagerHolder() == null || txObject.getEntityManagerHolder().isSynchronizedWithTransaction()) { EntityManager newEm = createEntityManagerForTransaction(); if (logger.isDebugEnabled()) { logger.debug("Opened new EntityManager [" + newEm + "] for JPA transaction"); } txObject.setEntityManagerHolder(new EntityManagerHolder(newEm), true); } EntityManager em = txObject.getEntityManagerHolder().getEntityManager(); // Delegate to JpaDialect for actual transaction begin. final int timeoutToUse = determineTimeout(definition); Object transactionData = getJpaDialect() .beginTransaction( em, new DelegatingTransactionDefinition(definition) { @Override public int getTimeout() { return timeoutToUse; } }); txObject.setTransactionData(transactionData); // Register transaction timeout. if (timeoutToUse != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getEntityManagerHolder().setTimeoutInSeconds(timeoutToUse); } // Register the JPA EntityManager's JDBC Connection for the DataSource, if set. if (getDataSource() != null) { ConnectionHandle conHandle = getJpaDialect().getJdbcConnection(em, definition.isReadOnly()); if (conHandle != null) { ConnectionHolder conHolder = new ConnectionHolder(conHandle); if (timeoutToUse != TransactionDefinition.TIMEOUT_DEFAULT) { conHolder.setTimeoutInSeconds(timeoutToUse); } if (logger.isDebugEnabled()) { logger.debug( "Exposing JPA transaction as JDBC transaction [" + conHolder.getConnectionHandle() + "]"); } TransactionSynchronizationManager.bindResource(getDataSource(), conHolder); txObject.setConnectionHolder(conHolder); } else { if (logger.isDebugEnabled()) { logger.debug( "Not exposing JPA transaction [" + em + "] as JDBC transaction because JpaDialect [" + getJpaDialect() + "] does not support JDBC Connection retrieval"); } } } // Bind the entity manager holder to the thread. if (txObject.isNewEntityManagerHolder()) { TransactionSynchronizationManager.bindResource( getEntityManagerFactory(), txObject.getEntityManagerHolder()); } txObject.getEntityManagerHolder().setSynchronizedWithTransaction(true); } catch (TransactionException ex) { closeEntityManagerAfterFailedBegin(txObject); throw ex; } catch (Exception ex) { closeEntityManagerAfterFailedBegin(txObject); throw new CannotCreateTransactionException( "Could not open JPA EntityManager for transaction", ex); } }
@Override protected void doJtaBegin(JtaTransactionObject txObject, TransactionDefinition definition) throws NotSupportedException, SystemException { int timeout = determineTimeout(definition); // Apply transaction name (if any) to WebLogic transaction. if (this.weblogicUserTransactionAvailable && definition.getName() != null) { try { if (timeout > TransactionDefinition.TIMEOUT_DEFAULT) { /* weblogic.transaction.UserTransaction wut = (weblogic.transaction.UserTransaction) ut; wut.begin(definition.getName(), timeout); */ this.beginWithNameAndTimeoutMethod.invoke( txObject.getUserTransaction(), definition.getName(), timeout); } else { /* weblogic.transaction.UserTransaction wut = (weblogic.transaction.UserTransaction) ut; wut.begin(definition.getName()); */ this.beginWithNameMethod.invoke(txObject.getUserTransaction(), definition.getName()); } } catch (InvocationTargetException ex) { throw new TransactionSystemException( "WebLogic's UserTransaction.begin() method failed", ex.getTargetException()); } catch (Exception ex) { throw new TransactionSystemException( "Could not invoke WebLogic's UserTransaction.begin() method", ex); } } else { // No WebLogic UserTransaction available or no transaction name specified // -> standard JTA begin call. applyTimeout(txObject, timeout); txObject.getUserTransaction().begin(); } // Specify isolation level, if any, through corresponding WebLogic transaction property. if (this.weblogicTransactionManagerAvailable) { if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { try { Transaction tx = getTransactionManager().getTransaction(); Integer isolationLevel = definition.getIsolationLevel(); /* weblogic.transaction.Transaction wtx = (weblogic.transaction.Transaction) tx; wtx.setProperty(ISOLATION_LEVEL_KEY, isolationLevel); */ this.setPropertyMethod.invoke(tx, ISOLATION_LEVEL_KEY, isolationLevel); } catch (InvocationTargetException ex) { throw new TransactionSystemException( "WebLogic's Transaction.setProperty(String, Serializable) method failed", ex.getTargetException()); } catch (Exception ex) { throw new TransactionSystemException( "Could not invoke WebLogic's Transaction.setProperty(String, Serializable) method", ex); } } } else { applyIsolationLevel(txObject, definition.getIsolationLevel()); } }