JTA分布式事務:Java Transaction API,允許應用程式執行分布式事務處理。
Atomikos:為java平台提供增值服務并且開源的事務管理器。
基于xa協定,xa協定是以兩階段送出協定為基礎的。
這種處理方案一般是針對傳統架構項目的分布式事務,不适合用在微服務架構中。
下面是springboot配置多個oracle資料源,重制分布式事務問題的例子
一、添加依賴
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.4</version>
</dependency>
<!-- 這裡使用的是JPA包,也可使用JDBC包進行 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
由于maven倉庫沒有ojdbc6,需要自行下載下傳安裝
二、修改application.yml配置檔案
spring:
jpa:
database: oracle
show-sql: true
datasource:
master:
jdbc-url: jdbc:oracle:thin:@127.0.0.1:1521:ORCL
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: oracle.jdbc.driver.OracleDriver
username: wx
password: 123
slave1:
jdbc-url: jdbc:oracle:thin:@127.0.0.1:1521:ORCL
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: oracle.jdbc.driver.OracleDriver
username: wl
password: 123456
三、建立資料源配置檔案
@Configuration
public class DataSourceConfig {
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource dataSource1(){
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.slave1")
public DataSource dataSource2(){
return DataSourceBuilder.create().build();
}
}
@Primary注釋表示這個資料源是預設資料源,如果沒有這個注釋的話,開啟事務的時候會報錯
四、建立JdbcTemplate配置類
@Configuration
public class JdbcTemplateConfig {
@Bean
public JdbcTemplate template1(@Qualifier("dataSource1")DataSource dataSource1){
return new JdbcTemplate(dataSource1);
}
@Bean
public JdbcTemplate template2(@Qualifier("dataSource2")DataSource dataSource2){
return new JdbcTemplate(dataSource2);
}
}
五、使用測試類進行測試
@RunWith(SpringRunner.class)
@SpringBootTest
public class JtaatomikosApplicationTests {
@Autowired
private JdbcTemplate template1;
@Autowired
private JdbcTemplate template2;
@Test
@Transactional
public void contextLoads() {
String sql = "INSERT INTO \"test\" VALUES('asd','張三','24')";
template1.update(sql);
template2.update(sql);
int i = 1/0;
}
}
test表隻有三個字段:id,name,age
表裡邊資料都是空的。
執行測試方法contextLoads
控制台會抛異常
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwczX0xiRGZkRGZ0Xy9GbvNGL2EzXlpXazxSP0clWvBHWZVnRXRWNs1WZoJlMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLxcTMwMjN1YTMwETOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
此時去資料庫檢視資料會發現
WL資料庫插入資料成功了。
WX資料庫插入資料失敗了。
WX資料庫是主資料源,說明主資料源事務復原成功了,但是副資料源事務沒有復原,這就是分布式事務問題。
為了解決這個問題,我們引入atomikos解決
在原來的項目基礎上,添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
修改資料源配置檔案
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource1(){
Properties properties = new Properties();
properties.setProperty("URL","jdbc:oracle:thin:@127.0.0.1:1521:ORCL");
properties.setProperty("user","wx");
properties.setProperty("password","123");
AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
atomikosDataSourceBean.setXaProperties(properties);
atomikosDataSourceBean.setUniqueResourceName("dataSource1");
atomikosDataSourceBean.setXaDataSourceClassName("oracle.jdbc.xa.client.OracleXADataSource");
return atomikosDataSourceBean;
}
@Bean
public DataSource dataSource2(){
Properties properties = new Properties();
properties.setProperty("URL","jdbc:oracle:thin:@127.0.0.1:1521:ORCL");
properties.setProperty("user","wl");
properties.setProperty("password","123456");
AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
atomikosDataSourceBean.setXaProperties(properties);
atomikosDataSourceBean.setUniqueResourceName("dataSource2");
atomikosDataSourceBean.setXaDataSourceClassName("oracle.jdbc.xa.client.OracleXADataSource");
return atomikosDataSourceBean;
}
}
可以發現,我們去掉了@Primary和@ConfigurationProperties注釋,手動設定資料庫參數,将資料源類型改成了AtomikoDataSourceBean類型,這個類型的資料源需要添加XADataSource類型的資料源參數,這裡我們添加的是OracleXADataSource,這個類就是JTA類型的。
現在我們就已經把事務交給引入進來的全局事務協調了。
執行測試方法contextLoads
可以發現控制台同樣抛出/ by zero異常,WX和WL資料庫都沒有插入資料,說明都進行事務復原了。