今天就跟大家聊聊有關(guān)如何剖析Spring高級事務(wù)管理難點,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
創(chuàng)新互聯(lián)是一家以網(wǎng)絡(luò)技術(shù)公司,為中小企業(yè)提供網(wǎng)站維護、成都網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)、網(wǎng)站備案、服務(wù)器租用、國際域名空間、軟件開發(fā)、小程序制作等企業(yè)互聯(lián)網(wǎng)相關(guān)業(yè)務(wù),是一家有著豐富的互聯(lián)網(wǎng)運營推廣經(jīng)驗的科技公司,有著多年的網(wǎng)站建站經(jīng)驗,致力于幫助中小企業(yè)在互聯(lián)網(wǎng)讓打出自已的品牌和口碑,讓企業(yè)在互聯(lián)網(wǎng)上打開一個面向全國乃至全球的業(yè)務(wù)窗口:建站服務(wù)熱線:13518219792
1、Spring事務(wù)傳播行為
所謂事務(wù)傳播行為就是多個事務(wù)方法相互調(diào)用時,事務(wù)如何在這些方法間傳播。Spring支持7種事務(wù)傳播行為
PROPAGATION_REQUIRED(加入已有事務(wù))
如果當(dāng)前沒有事務(wù),就新建一個事務(wù),如果已經(jīng)存在一個事務(wù)中,加入到這個事務(wù)中。這是最常見也是默認的方式。
PROPAGATION_SUPPORTS(跟隨環(huán)境)
支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù),就以非事務(wù)方式執(zhí)行。
PROPAGATION_MANDATORY(需要事務(wù))
使用當(dāng)前的事務(wù),如果當(dāng)前沒有事務(wù),就拋出異常。
PROPAGATION_REQUIRES_NEW(獨立事務(wù))
新建事務(wù),如果當(dāng)前存在事務(wù),把當(dāng)前事務(wù)掛起。
PROPAGATION_NOT_SUPPORTED(非事務(wù)方式)
以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起。
PROPAGATION_NEVER(排除事務(wù))
以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常。
PROPAGATION_NESTED(嵌套事務(wù))
如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行。如果當(dāng)前沒有事務(wù),則執(zhí)行與PROPAGATION_REQUIRED類似的操作。
Spring默認的事務(wù)傳播行為是PROPAGATION_REQUIRED,它適合于絕大多數(shù)的情況。假設(shè)ServiveX#methodX()都工作在事務(wù)環(huán)境下(即都被Spring事務(wù)增強了),假設(shè)程序中存在如下的調(diào)用鏈:Service1#method1()->Service2#method2()->Service3#method3(),那么這3個服務(wù)類的3個方法通過Spring的事務(wù)傳播機制都工作在同一個事務(wù)中。
如果在一個ServiceA和a()方法中啟動一個線程,在這個新創(chuàng)建的線程中執(zhí)行ServiceB的事務(wù)方法b()。在相同線程中進行相互嵌套調(diào)用的事務(wù)方法工作于相同的事務(wù)中。如果這些相互嵌套調(diào)用的方法工作在不同的線程中,不同線程下的事務(wù)方法工作在獨立的事務(wù)中。
2、多種數(shù)據(jù)持久方法事務(wù)管理
如果你采用了一個高端ORM技術(shù)(Hibernate,JPA,JDO),同時采用一個JDBC技術(shù)(Spring JDBC,iBatis),由于前者的會話(Session)是對后者連接(Connection)的封裝,Spring會“足夠智能地”在同一個事務(wù)線程讓前者的會話封裝后者的連接。所以,我們只要直接采用前者的事務(wù)管理器就可以了。下表給出了混合數(shù)據(jù)訪問技術(shù)所對應(yīng)的事務(wù)管理器:

1)不同持久方式的事務(wù)統(tǒng)一
Spring提供了一個能從當(dāng)前事務(wù)上下文中獲取綁定的數(shù)據(jù)連接的工具類,那就是DataSourceUtils。Spring強調(diào)必須使用DataSourceUtils工具類獲取數(shù)據(jù)連接。
static Connection doGetConnection(DataSource dataSource)
首先嘗試從事務(wù)上下文中獲取連接,失敗后再從數(shù)據(jù)源獲取連接;
static Connection getConnection(DataSource dataSource)
doGetConnection方法的功能一樣,實際上,它內(nèi)部就是調(diào)用doGetConnection方法獲取連接的;
static void doReleaseConnection(Connection con, DataSource dataSource)
釋放連接,放回到連接池中;
static void release Connection(Connection con, DataSource dataSource)
和doReleaseConnection方法的功能一樣,實際上,它內(nèi)部就是調(diào)用doReleaseConnection方法獲取連接的;
測試demo:
@Service public class TestTranscationServiceImpl implements TestTranscationService { @Autowired private TestTranscationDao testTranscationDao; @Override @Transactional public int test(){ testTranscationDao.update1(); testTranscationDao.update2(); return 0; } }@Autowired private JdbcTemplate jdbcTemplate; @Override public int update1() { //1.獲得數(shù)據(jù)庫連接 Connection con = DataSourceUtils.getConnection(jdbcTemplate.getDataSource()); try { con.prepareStatement("update grade_info set grade_name='11' where grade_id=1").executeUpdate(); } catch (SQLException e) { throw new RuntimeException(e); }finally { //2如果當(dāng)前方法沒有上下文事務(wù)管理,不釋放數(shù)據(jù)庫連接會造成數(shù)據(jù)庫連接泄露 //如果存在上下文事務(wù),調(diào)用或者不調(diào)用數(shù)據(jù)庫連接釋放都沒有問題 DataSourceUtils.releaseConnection(con, jdbcTemplate.getDataSource()); } return 0; } @Override public int update2(){ //3.獲得數(shù)據(jù)庫連接 和1的數(shù)據(jù)庫連接是同一個連接 Connection con = DataSourceUtils.getConnection(jdbcTemplate.getDataSource()); try { //4.這種方法取到的數(shù)據(jù)庫連接和 1,3取到的數(shù)據(jù)庫連接不同 Connection conn = jdbcTemplate.getDataSource().getConnection(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } return jdbcTemplate.update("update grade_info set grade_name='高中三年級' where grade_id=1"); }Spring為每個數(shù)據(jù)訪問技術(shù)框架都提供了一個獲取事務(wù)上下文綁定的數(shù)據(jù)連接(或其衍生品)的工具類和數(shù)據(jù)源(或其衍生品)的代理類。

2)Hibernate和JDBC混合使用注意事項
由于Hibernate一級緩存的原因,在通過save,update,delete等方法操作數(shù)據(jù)時,并沒有真正向數(shù)據(jù)庫發(fā)送SQL,只有調(diào)用flush()時,Hibernate才會將一級緩存中的狀態(tài)變化同步到數(shù)據(jù)庫中。
Hibernate的事務(wù)管理在提交事務(wù)時,會自動調(diào)用flush()操作,將一級緩存同步到數(shù)據(jù)庫中,此時才會將產(chǎn)生并向數(shù)據(jù)庫發(fā)送SQL語句。
正是因為以上原因的存在,所有在混合使用JDBC和Hibernate時,可能存在丟失更新的問題。

在混合使用Hibernate和JDBC時,JDBC的操作不會同步到Hibernate的緩存中(一級緩存及二級緩存),Hibernate緩存中的狀態(tài)變更也不被JDBC感知。因此混合使用時必須特別關(guān)注這一點。
由于混合數(shù)據(jù)訪問技術(shù)的方案的事務(wù)同步而緩存不同步的情況,所以***用Hibernate完成讀寫操作,而用Spring JDBC完成讀的操作。如用Spring JDBC進行簡要列表的查詢,而用Hibernate對查詢出的數(shù)據(jù)進行維護。如果確實要同時使用Hibernate和Spring JDBC讀寫數(shù)據(jù),則必須充分考慮到Hibernate緩存機制引發(fā)的問題:必須充分分析數(shù)據(jù)維護邏輯,根據(jù)需要,及時調(diào)用Hibernate的flush()方法,以免覆蓋Spring JDBC的更改,在Spring JDBC更改數(shù)據(jù)庫時,維護Hibernate的緩存。
3、Spring的事務(wù)增強限制條件
由于Spring事務(wù)管理是基于接口代理或動態(tài)字節(jié)碼技術(shù),通過AOP實施事務(wù)增強的。
對于基于接口動態(tài)代理的AOP事務(wù)增強來說,由于接口的方法是public的,這就要求實現(xiàn)類的實現(xiàn)方法必須是public的(不能是protected,private等),同時不能使用static的修飾符。所以,可以實施接口動態(tài)代理的方法只能是使用“public”或“public final”修飾符的方法,其它方法不可能被動態(tài)代理,相應(yīng)的也就不能實施AOP增強,也即不能進行Spring事務(wù)增強了。
基于CGLib字節(jié)碼動態(tài)代理的方案是通過擴展被增強類,動態(tài)創(chuàng)建子類的方式進行AOP增強植入的。由于使用final,static,private修飾符的方法都不能被子類覆蓋,相應(yīng)的,這些方法將不能被實施的AOP增強。所以,必須特別注意這些修飾符的使用,以免不小心成為事務(wù)管理的漏網(wǎng)之魚。
4、Spring事務(wù)管理的異常捕捉,事務(wù)回滾
spring的事務(wù)管理器只對 unchecked exception進行異常回滾,Error和RuntimeException及其子類是unchecked exception.其他exception是checked exception.
如果在service層中,使用了try ,catch來捕捉異常,導(dǎo)致sevice層出現(xiàn)的異常被 “截留”,無法拋出給事務(wù)管理器,這就給事務(wù)管理器造成一種假象,就像程序在運行中,沒有產(chǎn)生任何問題,因此也就不會對出現(xiàn) runtimeException進行回滾操作。
看完上述內(nèi)容,你們對如何剖析Spring高級事務(wù)管理難點有進一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。
新聞名稱:如何剖析Spring高級事務(wù)管理難點
URL網(wǎng)址:http://chinadenli.net/article24/jigcje.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、、定制網(wǎng)站、做網(wǎng)站、面包屑導(dǎo)航、網(wǎng)站營銷
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)