Skip to content

Instantly share code, notes, and snippets.

@xialeistudio
Created May 1, 2023 04:41
Show Gist options
  • Save xialeistudio/fec5cbf1bf31ba235139af792653dc4c to your computer and use it in GitHub Desktop.
Save xialeistudio/fec5cbf1bf31ba235139af792653dc4c to your computer and use it in GitHub Desktop.
atomikos distributed transaction
package com.example.jta;
import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.mysql.cj.jdbc.MysqlXADataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
public class Main {
public static void main(String[] args) {
UserTransactionManager utm = new UserTransactionManager();
utm.setForceShutdown(false);
UserTransaction userTransaction = new UserTransactionImp();
String databaseURL = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";
// order
MysqlXADataSource orderXADatasource = new MysqlXADataSource();
orderXADatasource.setURL(databaseURL);
orderXADatasource.setUser("root");
orderXADatasource.setPassword("root");
AtomikosDataSourceBean orderDatasource = new AtomikosDataSourceBean();
orderDatasource.setXaDataSource(orderXADatasource);
orderDatasource.setUniqueResourceName("order");
orderDatasource.setTestQuery("SELECT 1");
// product
MysqlXADataSource productXADatasource = new MysqlXADataSource();
productXADatasource.setURL(databaseURL);
productXADatasource.setUser("root");
productXADatasource.setPassword("root");
AtomikosDataSourceBean productDatasource = new AtomikosDataSourceBean();
productDatasource.setXaDataSource(productXADatasource);
productDatasource.setUniqueResourceName("product");
productDatasource.setTestQuery("SELECT 1");
// start transaction
try {
userTransaction.begin();
try (Connection orderConn = orderDatasource.getConnection();
Connection productConn = productDatasource.getConnection();
PreparedStatement stmt1 = productConn.prepareStatement("SELECT * FROM products WHERE id=? FOR UPDATE ")) {
stmt1.setInt(1, 1);
// query product
try (ResultSet rs = stmt1.executeQuery()) {
if (!rs.next()) {
throw new SQLException("query failed");
}
// reduce stock
try (PreparedStatement stmt3 = productConn.prepareStatement("UPDATE products SET stock=? WHERE id=?")) {
int stock = rs.getInt("stock") - 1;
stmt3.setInt(1, stock);
stmt3.setLong(2, 1);
if (stmt3.executeUpdate() == 0) {
throw new SQLException("update stock failed");
}
System.out.printf("reduce stock succeed, current stock %d\n", stock);
// insert order
try (PreparedStatement stmt2 = orderConn.prepareStatement(
"INSERT INTO orders (id, user_id, product_id, amount, status, created_at, updated_at) VALUES (NULL,?,?,?,?,NOW(),NOW())")) {
stmt2.setInt(1, 1);
stmt2.setInt(2, 1);
stmt2.setInt(3, 1);
stmt2.setByte(4, (byte) 0);
if (stmt2.executeUpdate() == 0) {
throw new SQLException("insert product failed");
}
System.out.print("insert product succeed\n");
}
}
}
try {
userTransaction.commit();
} catch (RollbackException | HeuristicMixedException | HeuristicRollbackException e) {
throw new RuntimeException(e);
}
}
} catch (SQLException | NotSupportedException | SystemException e) {
try {
userTransaction.rollback();
} catch (SystemException ex) {
throw new RuntimeException(ex);
}
throw new RuntimeException(e);
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>sharding-jdbc-example</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.32</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jta</artifactId>
<version>6.0.0M2</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jdbc</artifactId>
<version>6.0.0M2</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
</project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment