今天就跟大家聊聊有關Spring中怎么利用atomikos+druid實現(xiàn)分布式事務,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據(jù)這篇文章可以有所收獲。
創(chuàng)新互聯(lián)是一家集網(wǎng)站建設,蓮都企業(yè)網(wǎng)站建設,蓮都品牌網(wǎng)站建設,網(wǎng)站定制,蓮都網(wǎng)站建設報價,網(wǎng)絡營銷,網(wǎng)絡優(yōu)化,蓮都網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時我們時刻保持專業(yè)、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學習、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實用型網(wǎng)站。
XA是啥?
XA是由X/Open組織提出的分布式事務的架構(或者叫協(xié)議)。XA架構主要定義了(全局)事務管理器(Transaction Manager)和(局部)資源管理器(Resource Manager)之間的接口。XA接口是雙向的系統(tǒng)接口,在事務管理器(Transaction Manager)以及一個或多個資源管理器(Resource Manager)之間形成通信橋梁。也就是說,在基于XA的一個事務中,我們可以針對多個資源進行事務管理,例如一個系統(tǒng)訪問多個數(shù)據(jù)庫,或即訪問數(shù)據(jù)庫、又訪問像消息中間件這樣的資源。這樣我們就能夠實現(xiàn)在多個數(shù)據(jù)庫和消息中間件直接實現(xiàn)全部提交、或全部取消的事務。XA規(guī)范不是java的規(guī)范,而是一種通用的規(guī)范,
目前各種數(shù)據(jù)庫、以及很多消息中間件都支持XA規(guī)范。
JTA是滿足XA規(guī)范的、用于Java開發(fā)的規(guī)范。所以,當我們說,使用JTA實現(xiàn)分布式事務的時候,其實就是說,使用JTA規(guī)范,實現(xiàn)系統(tǒng)內多個數(shù)據(jù)庫、消息中間件等資源的事務。
JTA(Java Transaction API),是J2EE的編程接口規(guī)范,它是XA協(xié)議的JAVA實現(xiàn)。它主要定義了:
一個事務管理器的接口javax.transaction.TransactionManager,定義了有關事務的開始、提交、撤回等>操作。 一個滿足XA規(guī)范的資源定義接口javax.transaction.xa.XAResource,一種資源如果要支持JTA事務,就需要讓它的資源實現(xiàn)該XAResource接口,并實現(xiàn)該接口定義的兩階段提交相關的接口。如果我們有一個應用,它使用JTA接口實現(xiàn)事務,應用在運行的時候,就需要一個實現(xiàn)JTA的容器,一般情況下,這是一個J2EE容器,像JBoss,Websphere等應用服務器。但是,也有一些獨立的框架實現(xiàn)了JTA,例如Atomikos, bitronix 都提供了jar包方式的JTA實現(xiàn)框架。這樣我們就能夠在Tomcat或者Jetty之類的服務器上運行使用JTA實現(xiàn)事務的應用系統(tǒng)。在上面的本地事務和外部事務的區(qū)別中說到,JTA事務是外部事務,可以用來實現(xiàn)對多個資源的事務性。它正是通過每個資源實現(xiàn)的XAResource來進行兩階段提交的控制。感興趣的同學可以看看這個接口的方法,除了commit, rollback等方法以外,還有end(), forget(), isSameRM(), prepare()等等。光從這些接口就能夠想象JTA在實現(xiàn)兩階段事務的復雜性。
本篇以Spring MVC+Maven+Atomikos+Druid+MyBatis演示分布式事務的實現(xiàn)。
Mave 的pom.xml
spring-application-context.xml
spring-mybatis-atomikos-druid.xml
jdbc.properties
#mysql 6.*以上jdbc.driverClassName = com.mysql.cj.jdbc.Driverjdbc.url = jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8&pinGlobalTxToPhysicalConnection=true&useSSL=falsejdbc.username =rootjdbc.password =rootjdbc.two.url = jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8&pinGlobalTxToPhysicalConnection=true&useSSL=falsejdbc.two.username =rootjdbc.two.password =root
jta.properties
com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactorycom.atomikos.icatch.console_file_name=tm.release.outcom.atomikos.icatch.log_base_name=tm.releaselogcom.atomikos.icatch.tm_unique_name=com.atomikos.spring.jdbc.tm.releasecom.atomikos.icatch.console_log_level=INFO
TestInsert.java
@ContextConfiguration(value = {"classpath:spring-application-context.xml"})@RunWith(SpringJUnit4ClassRunner.class)public class TestInsert { private Logger logger = LoggerFactory.getLogger(TestInsert.class); @Autowired private BatchInsertService batchInsertService; @Test public void insert(){ long startTime = System.currentTimeMillis(); User user = new User(); user.setName("User_"+(int)(Math.random()*100)); user.setAge((int)(Math.random()*100)); CustInfo info = new CustInfo(); info.setPhone("123456789"+(int)(Math.random()*100)); batchInsertService.insert(user,info); long endTime = System.currentTimeMillis(); logger.info("共耗時:{}毫秒",endTime -startTime); }}
BatchInsertService.java
@Servicepublic class BatchInsertService { private Logger logger = LoggerFactory.getLogger(BatchInsertService.class); @Autowired private UserService userService; @Autowired private CustInfoService custInfoService; @Transactional(rollbackFor= {Exception.class,RuntimeException.class}) public void insert(User user,CustInfo custInfo) { int insertUser = userService.insert(user); logger.info("insertUser={}",insertUser); int insertCustInfo = custInfoService.insert(custInfo); logger.info("insertCustInfo={}",insertCustInfo); }}
UserService.java
@Servicepublic class UserService { @Autowired private UserMapper userMapper; public int insert(User record) { int result = userMapper.insert(record); return result; } }
CustInfoService.java
@Servicepublic class CustInfoService { @Autowired private CustInfoMapper custInfoMapper; public int insert(CustInfo record) { int result = custInfoMapper.insert(record); long now = System.currentTimeMillis(); // 模擬一個異常 if (now % 2 == 0) { throw new RuntimeException("CustInfoMapper throws test insert exception"); } return result; }}
看完上述內容,你們對Spring中怎么利用atomikos+druid實現(xiàn)分布式事務有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。