乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      深入spring事務(wù)管理

       印度阿三17 2018-09-26

      Spring事務(wù)的本質(zhì)其實(shí)就是數(shù)據(jù)庫(kù)對(duì)事務(wù)的支持,在沒有spring提供事務(wù)管理之前,純JDBC事務(wù)管理機(jī)制是利用java.sql.Connection對(duì)象完成對(duì)事務(wù)的提交;示例如下:

      public static void main(String[] args) throws SQLException {
      	//1.獲取連接
      	Connection conn = null;
      	try {  
      		conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/xx_db", "root", "root");
      		//2.開啟事務(wù):將自動(dòng)提交設(shè)置為false   
      		conn.setAutoCommit(false);                        
      		//3.執(zhí)行CRUD操作
      		//4.當(dāng)兩個(gè)操作成功后手動(dòng)提交 
      		conn.commit();       
      	} catch (Exception e) { 
      		//一旦其中一個(gè)操作出錯(cuò)都將回滾,所有操作都不成功
      		if(conn!=null){conn.rollback(); }
      		e.printStackTrace();  
      	} finally {
      		//5.關(guān)閉連接
      		if(conn!=null){conn.close();}
      	}
      }
      

      而使用Spring的事務(wù)管理功能后,我們可以不再寫步驟 1、2 、4、5 的代碼,而是由Spring 自動(dòng)完成,即通過AOP,Spring擦除了大量的try…catch…finally語句、打開關(guān)閉數(shù)據(jù)庫(kù)和事務(wù)回滾提交等冗余代碼。

      接下來我們主要來講下Spring數(shù)據(jù)庫(kù)事務(wù)管理:
      1.事務(wù)管理器的設(shè)計(jì)與配置
      Spring提供能夠事務(wù)管理器的模板是org.springframework.transaction.support.TransactionTemplate,其源碼里主要包含一個(gè)PlatformTransactionManager接口,事務(wù)的創(chuàng)建、提交、回滾都是通過這個(gè)接口完成的,默認(rèn)事務(wù)異常時(shí)會(huì)回滾,我們也可以通過配置修改在某些異常發(fā)生時(shí)不回滾事務(wù);
      PlatformTransactionManager是一個(gè)事務(wù)管理器,也是根管理器,其實(shí)在spring中有多種事務(wù)管理器,例如DataSourceTransactionManager,HibernateTransactionManager,WebSphereTransactionManager,JtaTransactionManager 等等;PlatformTransactionManager接口源碼如下:

      public interface PlatformTransactionManager {
      	//獲取事務(wù)狀態(tài)
      	TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
      	//提交事務(wù)
      	void commit(TransactionStatus status) throws TransactionException;
      	//回滾事務(wù)
      	void rollback(TransactionStatus status) throws TransactionException;
      }
      

      了解了事務(wù)管理的設(shè)計(jì)思路,接下來就以DataSourceTransactionManager為例配置事務(wù)管理器(MyBatis框架):
      (1)XML配置
      -XML的命名空間里引入事務(wù)命名空間:
      http://www./schema/tx
      http://www./schema/tx/spring-tx-4.0.xsd
      -XML中定義一個(gè)數(shù)據(jù)庫(kù)連接池的
      -配置數(shù)據(jù)源事務(wù)管理器,注入數(shù)據(jù)庫(kù)連接池,內(nèi)容如下:

      <bean id="transactionManager"
      	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      	<property name="dataSource" ref="dataSource" />
      </bean>
      

      經(jīng)過如上三步配置,Spring就知道已將數(shù)據(jù)庫(kù)事務(wù)委托給事務(wù)管理器了;
      (2)Java配置

      @Configuration
      @ComponentScan("cn.infocore.transaction.*")
      @EnableTransactionManagement  //使用事務(wù)驅(qū)動(dòng)管理器
      public class JavaConfig implements TransactionManagementConfigurer{
      	private DataSource ds=null;
      	
      	//配置數(shù)據(jù)源
      	@Bean(name="ds")
      	public DataSource initDB(){
      		if(ds!=null){
      			return ds;
      		}
      		Properties props=new Properties();
      		props.setProperty("driverClassName", "com.mysql.jdbc.Driver");
      		props.setProperty("url", "jdbc:mysql://localhost:3306/xx_db");
      		props.setProperty("username", "root");
      		props.setProperty("password", "root");
      		props.setProperty("maxActive", "200");
      		props.setProperty("maxIdle", "20");
      		props.setProperty("maxWait", "30000");
      		try {
      			ds=BasicDataSourceFactory.createDataSource(props);
      		} catch (Exception e) {
      			e.printStackTrace();
      		}
      		return ds;
      	}
      	
      	//配置JdbcTemplate
      	@Bean(name="jdbcTemplate")
      	public JdbcTemplate initJdbcTemplate(){
      		JdbcTemplate jdbc=new JdbcTemplate();
      		jdbc.setDataSource(initDB());
      		return jdbc;
      	}
      
      	//實(shí)現(xiàn)接口方法,使得返回?cái)?shù)據(jù)庫(kù)事務(wù)管理
      	@Override
      	public PlatformTransactionManager annotationDrivenTransactionManager() {
      		DataSourceTransactionManager manager=new DataSourceTransactionManager();
      		manager.setDataSource(initDB());
      		return manager;
      	}
      }
      

      2.在spring中可以使用聲明式事務(wù)和編程式事務(wù),后者由于會(huì)產(chǎn)生冗余代碼,現(xiàn)已幾乎不用;聲明式事務(wù)又可分為XML配置和注解事務(wù),XML也已不常用,目前主流事務(wù)處理方法是@Transactional;
      (1)編程式事務(wù):事務(wù)的定義獲取、SQL執(zhí)行、事務(wù)的提交回滾都由開發(fā)者自己實(shí)現(xiàn);唯一的優(yōu)點(diǎn)就是代碼流程清晰,但不推薦使用,代碼就不詳述了;
      (2)聲明式事務(wù):一種約定型事務(wù),spring給了一個(gè)約定,AOP技術(shù);當(dāng)業(yè)務(wù)正?;虍惓r(shí),spring會(huì)讓事務(wù)管理器提交或回滾事務(wù);介于聲明式事務(wù)是重點(diǎn),因此會(huì)詳細(xì)分析,先看下流程圖和Transactional源碼:
      在這里插入圖片描述

      @Target({ElementType.METHOD, ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Inherited
      @Documented
      public @interface Transactional {
      	//定義事務(wù)管理器,值是IoC容器中的一個(gè)beanId,這個(gè)bean需實(shí)現(xiàn)接口PlatformTransactionManager
      	@AliasFor("transactionManager")
      	String value() default ""; 
      	//同上
      	@AliasFor("value")
      	String transactionManager() default "";
      	//傳播行為
      	Propagation propagation() default Propagation.REQUIRED;
      	//隔離級(jí)別
      	Isolation isolation() default Isolation.DEFAULT;
      	//超時(shí)時(shí)間,單位秒,會(huì)引發(fā)異常,默認(rèn)會(huì)導(dǎo)致事務(wù)回滾
      	int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
      	//是否開啟只讀事務(wù),默認(rèn)false
      	boolean readOnly() default false;
      	//回滾事務(wù)的異常類定義:當(dāng)產(chǎn)生所定義異常時(shí),才會(huì)回滾
      	Class<? extends Throwable>[] rollbackFor() default {};
      	//回滾事務(wù)異常類名定義,同上,只是這個(gè)是使用類名稱定義
      	String[] rollbackForClassName() default {};
      	//當(dāng)產(chǎn)生哪些異常時(shí)不回滾事務(wù)
      	Class<? extends Throwable>[] noRollbackFor() default {};
      	//當(dāng)產(chǎn)生哪些類名稱定義的異常時(shí),不回滾事務(wù)
      	String[] noRollbackForClassName() default {};
      }
      

      Transactional源碼所定義的屬性都會(huì)被spring放到事務(wù)定義類TransactionDefinition中,接下來就是如何使用了;以最常使用的@Transactional注解為例:
      -XML配置事務(wù)攔截器:定義事務(wù)屬性與作用類

      <!--配置注解驅(qū)動(dòng),加入下面一行,就可以使用@Transactional配置事務(wù)了-->
      <tx:annotation-driven transaction-manager="transactionManager"/>
      <!-- 事務(wù)攔截器:攔截正則表達(dá)式匹配的方法 -->
      <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
      	<property name="transactionManager" value="transactionManager" /> <!-- 事務(wù)管理器 -->
      	<property name="transactionAttributes"><!-- 配置事務(wù)屬性 -->
      		<props>
      			<!-- key代表業(yè)務(wù)方法的正則表達(dá)式,內(nèi)容是配置各類事務(wù)定義參數(shù) -->
      			<prop key="insert*">PROPAGATION_REQUIRED,ISOLATION_READ_UNCOMMITTED</prop>
      			<prop key="select*">PROPAGATION_REQUIRED,readOnly</prop>
      		</props>
      	</property>
      </bean>
      <!-- 事務(wù)攔截器:攔截哪些類 -->
      <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
      	<property name="beanNames">
      		<list><value>*ServiceImpl</value></list>
      	</property>
      	<property name="interceptorNames">
      		<list><value>transactionInterceptor</value></list>
      	</property>
      </bean>
      

      在定義完事務(wù)管理器、攔截器后,接下來就是編寫業(yè)務(wù)代碼了,示例如下:

      @Autowired
      private RoleDao roleDao=null;
      
      @Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,timeout=3)
      public int insertRole(Role role){
      	return roleDao.insert(role);
      }
      

      3.數(shù)據(jù)庫(kù)相關(guān)
      (1)數(shù)據(jù)庫(kù)事務(wù)ACID特性:
      原子性Atomicity:整個(gè)事務(wù)中所有操作要么全部成功要么全部失敗,中間異常會(huì)回滾;
      一致性Consistency:事務(wù)在完成時(shí),必須是所有的數(shù)據(jù)都保持一致狀態(tài);
      隔離性Isolation:并發(fā)事務(wù)執(zhí)行之間無影響,在一個(gè)事務(wù)內(nèi)部的操作對(duì)其他事務(wù)是不產(chǎn)生影響,這需要事務(wù)隔離級(jí)別來指定隔離性;
      持久性Durability:一旦事務(wù)完成,數(shù)據(jù)庫(kù)的改變必須是持久化的;

      主要說一下隔離性,這個(gè)涉及到隔離級(jí)別,需要設(shè)置隔離級(jí)別是因?yàn)楫?dāng)同一數(shù)據(jù)被多個(gè)事務(wù)同時(shí)訪問時(shí),壓制丟失更新的產(chǎn)生;注意只是壓制,而不是消除,因?yàn)榭紤]到性能問題,過多的鎖會(huì)導(dǎo)致大量線程被掛起和恢復(fù),從而導(dǎo)致系統(tǒng)緩慢;
      第一類丟失更新:操作同一數(shù)據(jù),一個(gè)事務(wù)回滾而另一個(gè)事務(wù)操作后提交而引發(fā)數(shù)據(jù)不一致;目前大部分?jǐn)?shù)據(jù)庫(kù)已克服這類丟失;
      第二類丟失更新:操作同一數(shù)據(jù),多個(gè)事務(wù)同時(shí)提交而引發(fā)數(shù)據(jù)不一致;此類丟失目前有如下4中隔離級(jí)別:
      (1)未提交讀READ UNCOMMITTED
      允許一個(gè)事務(wù)讀取另一個(gè)事務(wù)未提交的數(shù)據(jù);最低隔離,最危險(xiǎn)(讀取到另一個(gè)事務(wù)的未提交數(shù)據(jù)操作后,另一個(gè)事務(wù)回滾了,就出現(xiàn)臟讀),應(yīng)用不大;優(yōu)點(diǎn)是并發(fā)能力高,適合對(duì)數(shù)據(jù)一致性沒有高要求而追求高并發(fā)的場(chǎng)景;
      (2)讀寫提交READ COMMITTED
      一個(gè)事務(wù)只能讀取另外一個(gè)事務(wù)已提交數(shù)據(jù);會(huì)出現(xiàn)不可重復(fù)讀(針對(duì)一條記錄)問題;
      (3)可重復(fù)讀
      針對(duì)(2)中出現(xiàn)的不可重復(fù)讀,如某個(gè)數(shù)據(jù)被一個(gè)事務(wù)讀取,另一個(gè)事務(wù)再去讀取只能阻塞直到前一個(gè)事務(wù)提交;會(huì)出現(xiàn)幻讀(針對(duì)多條記錄)問題;
      (4)串行化SERIALIZABLE
      所有SQL按照順序執(zhí)行,最高隔離;
      總之,(1)可能出現(xiàn)臟讀、不可重復(fù)讀、幻讀;(2)可能出現(xiàn)不可重復(fù)讀、幻讀;(3)可能出現(xiàn)幻讀;所以使用時(shí),要結(jié)合性能和數(shù)據(jù)一致性一起考慮,一般會(huì)以讀寫提交為主;Oracle只支持讀寫提交和串行化,默認(rèn)讀寫提交;MySQL都支持,默認(rèn)可重復(fù)讀;當(dāng)業(yè)務(wù)并發(fā)量不是很大的情況,可以使用串行化來保證數(shù)據(jù)一致性;

      (2)傳播行為
      方法之間調(diào)用事務(wù)采取的策略問題;一般情況下,數(shù)據(jù)庫(kù)事務(wù)都是要么全部成功要么全部失敗的機(jī)制,但也會(huì)出現(xiàn)其他情況,例如批量操作,只需要回滾失敗操作即可,這就涉及到事務(wù)的傳播行為;
      傳播行為有如下7種:
      REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED):需要事務(wù),默認(rèn),如當(dāng)前存在事務(wù),就沿用,否則新建一個(gè)事務(wù)運(yùn)行子方法;
      SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS):支持事務(wù),如當(dāng)前存在事務(wù),就沿用,不存在就繼續(xù)采用無事務(wù)方式;
      MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY):必須使用事務(wù),如當(dāng)前存在事務(wù),就沿用,否則拋出異常;
      REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW):新建事務(wù),無論當(dāng)前事務(wù)是否存在,都新建新事務(wù),新事務(wù)有自己獨(dú)立的隔離級(jí)別與鎖等特性;
      NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED):不支持事務(wù),當(dāng)前存在事務(wù)時(shí),掛起事務(wù);
      NEVER(TransactionDefinition.PROPAGATION_NEVER):不支持事務(wù),當(dāng)前存在事務(wù)時(shí),拋出異常,否則繼續(xù)采用無事務(wù)方式;
      NESTED(TransactionDefinition.PROPAGATION_NESTED):當(dāng)前方式調(diào)用子方法時(shí),子方法發(fā)生異常,只回滾子方法SQL,新事務(wù)沿用當(dāng)前事務(wù)的隔離級(jí)別和鎖等機(jī)制;如果數(shù)據(jù)庫(kù)支持保存點(diǎn)技術(shù),就啟用,否則就等價(jià)于REQUIRES_NEW;

      4.一些注意點(diǎn)
      (1)@Transactional,可以注解在類或方法或接口上,注解在類上表示這個(gè)類的所有public非靜態(tài)方法都將啟用事務(wù)功能,推薦放在實(shí)現(xiàn)類上;其底層實(shí)現(xiàn)是Spring AOP技術(shù),而AOP使用的是動(dòng)態(tài)代理,那對(duì)于靜態(tài)方法和非public方法,注釋@Transactional是失效的;
      (2)@Transactional自調(diào)用是失效的,即在@Transactional注解的方法或類中調(diào)用自己類中定義的方法是失效的,是因?yàn)锳OP的原理是動(dòng)態(tài)代理,自調(diào)用是類自身的調(diào)用,而不是代理對(duì)象去調(diào)用,就不會(huì)產(chǎn)生AOP,Spring就不能把代碼織入約定流程;
      解決方法:
      -用一個(gè)Service去調(diào)用另一個(gè)Servic,即再寫一個(gè)Service;
      -從Spring IoC容器中獲取代理對(duì)象getBean()去啟用AOP;
      (3)典型錯(cuò)誤
      –使用帶有事務(wù)的Service定義的方法時(shí)(有@Transactional注解),多次調(diào)用,并不在同一個(gè)事務(wù)里,spring每次都會(huì)創(chuàng)建新的數(shù)據(jù)庫(kù)事務(wù),完成后就會(huì)釋放,因此這種操作是不可能解決都成功或失敗的提交或回滾的;
      –過長(zhǎng)時(shí)間占用事務(wù):使用數(shù)據(jù)庫(kù)事務(wù)過程中,有占用時(shí)間比較久的且與數(shù)據(jù)庫(kù)事務(wù)無關(guān)的操作(讀寫文件、通信連接等),在并發(fā)請(qǐng)求多且性能要求高的環(huán)境就會(huì)出現(xiàn)請(qǐng)求卡頓的情況,嚴(yán)重的可能會(huì)出現(xiàn)宕機(jī);建議將這類操作提取出來,在事務(wù)關(guān)閉后執(zhí)行,這樣就可以避免長(zhǎng)時(shí)間占用事務(wù)導(dǎo)致系統(tǒng)性能降低;
      –錯(cuò)誤捕捉異常:主要是開發(fā)者在代碼中使用try…catch…捕獲了異常,導(dǎo)致spring在數(shù)據(jù)庫(kù)事務(wù)所約定的流程中再也得不到任何異常信息了,因此就會(huì)提交事務(wù),并不會(huì)因?yàn)楫惓6貪L了;
      解決方法:在catch里
      -手動(dòng)拋出異常:throw new RuntimException(ex);
      -手動(dòng)事務(wù)回滾: TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
      –異常種類:Spring管理事務(wù)默認(rèn)是RuntimeException或者Error,對(duì)于非運(yùn)行時(shí)異常來說,可以通過設(shè)置rollbackfor(發(fā)生指定異常時(shí)回滾)、rollbackForClassName、noRollbackFor(發(fā)生指定異常時(shí)不會(huì)滾)、noRollbackForClassName來指定在什么異常的情況下依舊提交事務(wù),在什么異常下回滾事務(wù);例如:@Transactional(rollbackFor = Exception.class),表示發(fā)生非運(yùn)行時(shí)異常時(shí)回滾;

      來源:http://www./content-4-24736.html

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多