- 浏览: 49771 次
- 性别:
- 来自: 成都
最新评论
-
洞中有怪兽:
osworkflow+spring+jdbc实现 -
呵呵呵123:
osuser.xml配置怎么配啊
osworkflow+spring+jdbc实现 -
zhaoyangjay:
你是不是改过JAR包中的源代码了,AbstractWorkfl ...
osworkflow dynamic split 动态会签的实现 -
dingchao.lonton:
TheMatrix 写道有个问题,例子中都是用同一个用户去执行 ...
osworkflow dynamic split 动态会签的实现 -
TheMatrix:
有个问题,例子中都是用同一个用户去执行doAction三遍,现 ...
osworkflow dynamic split 动态会签的实现
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源代码是Java开发者深入了解Spring框架工作原理的重要资源。这个版本的Spring框架在2004年发布,标志着Spring框架发展的早期阶段,它包含了许多核心特性,为现代企业级Java应用奠定了基础。在这个源代码...
通过对Spring3.0.5源代码的深入研究,开发者可以更好地理解其工作原理,从而优化自己的代码,提升应用程序的性能和稳定性。同时,这也是学习设计模式和最佳实践的好机会,因为Spring框架本身就是一个优秀的示例,...
"springTransaction"这个文件可能是项目的源代码,其中包含了转账业务逻辑的实现。在这个示例中,可能会有若干个带有@Transactional注解的方法,比如`transferMoney()`,它会调用两个数据库操作,分别对应于扣款和...
在这里,我们将深入探讨Spring 2.5.6源代码和API中的一些重要知识点。 1. **依赖注入(Dependency Injection, DI)**:Spring的核心特性之一就是依赖注入,它允许开发者通过配置文件或注解来管理对象之间的依赖关系...
`spring_transaction.txt`会详细阐述如何配置事务管理,以及@Transactional注解的使用。 7. **Spring安全(Spring Security)**: `spring_security.sql`和`spring_security.txt`可能涉及到Spring Security的基本...
"spring-transaction.jar"正是提供了Spring事务管理的类库,它包含了一系列用于处理事务的接口、类和配置元素,使得开发者能够方便地实现事务控制。 一、Spring 事务管理概述 Spring事务管理分为编程式事务管理和...
在源代码中,`org.springframework.beans` 和 `org.springframework.context` 包含了关于IoC容器的主要实现,如`BeanFactory`和`ApplicationContext`接口,它们提供了配置和管理bean的能力。 2. **依赖注入**:...
本篇主要聚焦于"Spring 常用 Transaction Annotation",即声明式事务管理,这是一种更简洁、易于维护的事务控制方式。 首先,Spring的声明式事务管理基于AOP(面向切面编程),它允许我们在不修改业务代码的情况下...
源代码是理解任何软件系统内部运作的关键,对于Spring框架而言,通过阅读源码,我们可以深入理解其设计理念和实现机制。 在Spring框架的源代码中,有几个关键部分值得我们关注: 1. **IoC容器**:这是Spring的核心...
在Spring配置文件中,我们需要配置数据源、MyBatis的配置文件路径以及映射文件的位置。 ```xml <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> ...
在源代码中,`org.springframework.transaction.interceptor`包下的类实现了事务的切面处理。 总的来说,深入分析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 ...
相关代码位于`org.springframework.transaction`包下。 Spring还提供了数据访问抽象,包括JDBC、ORM(Object-Relational Mapping)和OXM(Object-XML Mapping)。例如,`JdbcTemplate`和`SimpleJdbcInsert`使得JDBC...
### Spring中的Transaction事务传播行为种类详解 #### 一、引言 在开发基于Spring框架的应用程序时,事务管理是确保数据一致性的重要手段之一。Spring框架提供了丰富的事务管理功能,其中包括了事务传播行为...
在实际项目中,`springtransaction`工程可能是包含了一个完整的示例,用于演示如何在MyEclipse环境中配置和使用Spring的事务管理功能。开发者可以通过导入此工程,学习和实践Spring事务管理的配置与使用,从而更好地...
《Spring Framework 3.2.5.RELEASE 源代码深度解析》 Spring Framework作为Java领域最广泛应用的轻量级框架之一,其3.2.5.RELEASE版本的源代码蕴含了丰富的设计思想和技术实现。深入理解这个版本的源代码,不仅可以...
org.springframework.transaction-3.2.2.RELEASE最新版本
`javaee-core.jar`可能包含了J2EE核心库的部分源代码或类库,这些库提供了诸如EJB(Enterprise JavaBeans)、JMS(Java Message Service)、JTA(Java Transaction API)等关键服务的接口和实现。通过查看这些源代码...
在深入研究Spring 2.5的源代码之前,我们需要理解Spring的核心概念和架构。 1. **依赖注入(Dependency Injection, DI)**:Spring的核心特性之一是依赖注入,它允许对象在运行时通过容器进行装配,而不是在代码...
Spring笔记中提到的技术知识点主要围绕Hibernate框架展开,Hibernate是一个开放源代码的对象关系映射(Object/Relational Mapping,简称ORM)框架,用于Java环境。它对JDBC进行了非常轻量级的对象封装,使得开发者...