先看下Spring的 事务传播行为类型

 

事务传播行为类型

说明

PROPAGATION_REQUIRED

如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是 最常见的选择。

PROPAGATION_SUPPORTS

支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY

使用当前的事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW

新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER

以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作。

当使用 PROPAGATION_NESTED 时, 底层的数据源必须基于 JDBC 3.0 ,并且实现者需要支持保存点事务机制。

 

readOnly
      事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务。这 是一个最优化提示

 


Timeout


       在事务属性中还有定义“timeout”值的选项,指定事务超时为几秒。在JTA中,这将被简单地传递到J2EE服务器的事务协调程序,并据此得到相应的 解释。


在xml中的设置应该是 timeout_11 表示超时为11秒。。


为什么呢。。看下面的源码可知。。


Java代码



/** 
    
  * PropertyEditor for TransactionAttribute objects. Takes Strings of form 
    
  * <p><code>PROPAGATION_NAME,ISOLATION_NAME,readOnly,timeout_NNNN,+Exception1,-Exception2</code> 
    
  * <p>where only propagation code is required. For example: 
    
  * <p><code>PROPAGATION_MANDATORY,ISOLATION_DEFAULT</code> 
    
  * 
    
  * <p>The tokens can be in <strong>any</strong> order. Propagation and isolation codes 
    
  * must use the names of the constants in the TransactionDefinition class. Timeout values 
    
  * are in seconds. If no timeout is specified, the transaction manager will apply a default 
    
  * timeout specific to the particular transaction manager. 
    
  * 
    
  * <p>A "+" before an exception name substring indicates that 
    
  * transactions should commit even if this exception is thrown; 
    
  * a "-" that they should roll back. 
    
  * 
    
  * @author Rod Johnson 
    
  * @author Juergen Hoeller 
    
  * @since 24.04.2003 
    
  * @see org.springframework.transaction.TransactionDefinition 
    
  * @see org.springframework.core.Constants 
    
  */ 
    
 public class TransactionAttributeEditor extends PropertyEditorSupport { 
    

     /** 
    
      * Format is PROPAGATION_NAME,ISOLATION_NAME,readOnly,timeout_NNNN,+Exception1,-Exception2. 
    
      * Null or the empty string means that the method is non transactional. 
    
      * @see java.beans.PropertyEditor#setAsText(java.lang.String) 
    
      */ 
    
     public void setAsText(String s) throws IllegalArgumentException { 
    
         if (s == null || "".equals(s)) { 
    
             setValue(null); 
    
         } 
    
         else {    
    
             // tokenize it with "," 
    
             String[] tokens = StringUtils.commaDelimitedListToStringArray(s); 
    
             RuleBasedTransactionAttribute attr = new RuleBasedTransactionAttribute(); 
    

             for (int i = 0; i < tokens.length; i++) { 
    
                 String token = tokens[i].trim(); 
    
                 if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_PROPAGATION)) { 
    
                     attr.setPropagationBehaviorName(token); 
    
                 } 
    
                 else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_ISOLATION)) { 
    
                     attr.setIsolationLevelName(token); 
    
                 } 
    
                 else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_TIMEOUT)) { 
    
                     String value = token.substring(DefaultTransactionAttribute.PREFIX_TIMEOUT.length()); 
    
                     attr.setTimeout(Integer.parseInt(value)); 
    
                 } 
    
                 else if (token.equals(RuleBasedTransactionAttribute.READ_ONLY_MARKER)) { 
    
                     attr.setReadOnly(true); 
    
                 } 
    
                 else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_COMMIT_RULE)) { 
    
                     attr.getRollbackRules().add(new NoRollbackRuleAttribute(token.substring(1))); 
    
                 } 
    
                 else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_ROLLBACK_RULE)) { 
    
                     attr.getRollbackRules().add(new RollbackRuleAttribute(token.substring(1))); 
    
                 } 
    
                 else { 
    
                     throw new IllegalArgumentException("Illegal transaction attribute token: [" + token + "]"); 
    
                 } 
    
             } 
    

             setValue(attr); 
    
         } 
    
     } 
    

 }

/**
 * PropertyEditor for TransactionAttribute objects. Takes Strings of form
 * <p><code>PROPAGATION_NAME,ISOLATION_NAME,readOnly,timeout_NNNN,+Exception1,-Exception2</code>
 * <p>where only propagation code is required. For example:
 * <p><code>PROPAGATION_MANDATORY,ISOLATION_DEFAULT</code>
 *
 * <p>The tokens can be in <strong>any</strong> order. Propagation and isolation codes
 * must use the names of the constants in the TransactionDefinition class. Timeout values
 * are in seconds. If no timeout is specified, the transaction manager will apply a default
 * timeout specific to the particular transaction manager.
 *
 * <p>A "+" before an exception name substring indicates that
 * transactions should commit even if this exception is thrown;
 * a "-" that they should roll back.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @since 24.04.2003
 * @see org.springframework.transaction.TransactionDefinition
 * @see org.springframework.core.Constants
 */
public class TransactionAttributeEditor extends PropertyEditorSupport {

	/**
	 * Format is PROPAGATION_NAME,ISOLATION_NAME,readOnly,timeout_NNNN,+Exception1,-Exception2.
	 * Null or the empty string means that the method is non transactional.
	 * @see java.beans.PropertyEditor#setAsText(java.lang.String)
	 */
	public void setAsText(String s) throws IllegalArgumentException {
		if (s == null || "".equals(s)) {
			setValue(null);
		}
		else {	
			// tokenize it with ","
			String[] tokens = StringUtils.commaDelimitedListToStringArray(s);
			RuleBasedTransactionAttribute attr = new RuleBasedTransactionAttribute();

			for (int i = 0; i < tokens.length; i++) {
				String token = tokens[i].trim();
				if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_PROPAGATION)) {
					attr.setPropagationBehaviorName(token);
				}
				else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_ISOLATION)) {
					attr.setIsolationLevelName(token);
				}
				else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_TIMEOUT)) {
					String value = token.substring(DefaultTransactionAttribute.PREFIX_TIMEOUT.length());
					attr.setTimeout(Integer.parseInt(value));
				}
				else if (token.equals(RuleBasedTransactionAttribute.READ_ONLY_MARKER)) {
					attr.setReadOnly(true);
				}
				else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_COMMIT_RULE)) {
					attr.getRollbackRules().add(new NoRollbackRuleAttribute(token.substring(1)));
				}
				else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_ROLLBACK_RULE)) {
					attr.getRollbackRules().add(new RollbackRuleAttribute(token.substring(1)));
				}
				else {
					throw new IllegalArgumentException("Illegal transaction attribute token: [" + token + "]");
				}
			}

			setValue(attr);
		}
	}

}


从上面可以看出  token.substring() 这个方法把前缀timeout_给去掉了。。所以只剩下11了


从源码可看出来,PREFIX_XXXX  大都是这样写的,但前缀却是写在后面的。。觉得是不是命名有点古怪了,应该是XXXX_PREFIX,害我分析了一段时间。不过在源码上面的解释倒很清 楚:

* PropertyEditor for TransactionAttribute objects. Takes Strings of form
  * <p><code>PROPAGATION_NAME,ISOLATION_NAME,readOnly,timeout_NNNN,+Exception1,-Exception2</code>
  * <p>where only propagation code is required. For example:
  * <p><code>PROPAGATION_MANDATORY,ISOLATION_DEFAULT</code>

文笔不好。。就给出个实例,我想一看就该明白了。


Xml代码


<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> 
    
         <!--  事务拦截器bean需要依赖注入一个事务管理器 --> 
    
         <property name="transactionManager" ref="transactionManager"/> 
    
         <property name="transactionAttributes"> 
    
             <!--  下面定义事务传播属性--> 
    
             <props> 
    
                 <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> 
    
                 <prop key="*">PROPAGATION_REQUIRED,timeout_11</prop> 
    
             </props> 
    
         </property> 
    
     </bean>



<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
	    <!--  事务拦截器bean需要依赖注入一个事务管理器 -->
        <property name="transactionManager" ref="transactionManager"/>
    	<property name="transactionAttributes">
		    <!--  下面定义事务传播属性-->
		    <props>
			    <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
		    	<prop key="*">PROPAGATION_REQUIRED,timeout_11</prop>
		    </props>
	    </property>
	</bean>


总结先到这里。。等深入研究的时候再把写详细些。。。


 


 


事务隔离级别




      数据库并发操作存在的异常情况:
1. 更新丢失(Lost update):


2. 脏读取(Dirty Reads):


3. 不可重复读取(Non-repeatable Reads):


4. 两次更新问题(Second lost updates problem):


5. 幻读(Phantom Reads):


      为了避免上面出现几种情况在标准SQL规范中定义了4个事务隔离级别,不同隔离级别对事务处理不同 。


1.未授权读取(Read Uncommitted):


2. 授权读取(Read Committed):


3. 可重复读取(Repeatable Read):


4. 串行(Serializable):



隔离级别     更新丢失 脏读取 重复读取 幻读
未授权读取     N            Y         Y          Y
授权读取        N            N         Y          Y
可重复 读取     N            N         N         Y
串行               N            N         N         N