admin 1 năm trước cách đây
mục cha
commit
4c78a0a91a

+ 66 - 0
jtaSpringBoot/pom.xml

@@ -0,0 +1,66 @@
+<?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>jtaSpringBoot</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.2.2.RELEASE</version>
+    </parent>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-jta-atomikos</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-jdbc</artifactId>
+            <version>4.2.5.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 35 - 0
jtaSpringBoot/src/main/java/org/example/DataSourceConfiguration.java

@@ -0,0 +1,35 @@
+package org.example;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+import javax.sql.DataSource;
+
+@Configuration
+public class DataSourceConfiguration {
+
+    @Primary
+    @Bean
+    @ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.primary")
+    public DataSource primaryDataSource() {
+        return new AtomikosDataSourceBean();
+    }
+    @Bean
+    @ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.secondary")
+    public DataSource secondaryDataSource() {
+        return new AtomikosDataSourceBean();
+    }
+    @Bean
+    public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
+        return new JdbcTemplate(primaryDataSource);
+    }
+    @Bean
+    public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
+        return new JdbcTemplate(secondaryDataSource);
+    }
+}

+ 12 - 0
jtaSpringBoot/src/main/java/org/example/Main.java

@@ -0,0 +1,12 @@
+package org.example;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.ComponentScan;
+
+@SpringBootApplication
+public class Main {
+    public static void main(String[] args){
+        SpringApplication.run(Main.class, args);
+    }
+}

+ 42 - 0
jtaSpringBoot/src/main/java/org/example/TestService.java

@@ -0,0 +1,42 @@
+package org.example;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
+
+import javax.transaction.Transactional;
+
+@Service
+public class TestService {
+
+    private JdbcTemplate primaryJdbcTemplate;
+    private JdbcTemplate secondaryJdbcTemplate;
+    public TestService(JdbcTemplate primaryJdbcTemplate, JdbcTemplate secondaryJdbcTemplate) {
+        this.primaryJdbcTemplate = primaryJdbcTemplate;
+        this.secondaryJdbcTemplate = secondaryJdbcTemplate;
+    }
+    @Transactional
+    public void tx() {
+//        String sql="insert into User values(?,?)";
+//        Object[] args= {30, "aaa"};
+//        int update = primaryJdbcTemplate.update(sql, args);
+//        int update2 = secondaryJdbcTemplate.update(sql, args);
+//        System.out.println(update);
+//        System.out.println(update2);
+        // 修改test1库中的数据
+        primaryJdbcTemplate.update("update user set age = ? where name = ?", 30, "aaa");
+        // 修改test2库中的数据
+        secondaryJdbcTemplate.update("update user set age = ? where name = ?", 30, "aaa");
+    }
+    @Transactional
+    public void tx2() {
+        // 修改test1库中的数据
+//        String sql="insert into User values(?,?)";
+//        Object[] args= {"aaa", 30};
+//        int update = primaryJdbcTemplate.update(sql, args);
+//        System.out.println(update);
+        primaryJdbcTemplate.update("update user set age = ? where name = ?", 40, "aaa");
+        // 模拟:修改test2库之前抛出异常
+        throw new RuntimeException();
+    }
+}

+ 21 - 0
jtaSpringBoot/src/main/resources/application.properties

@@ -0,0 +1,21 @@
+spring.jta.enabled=true
+
+spring.jta.atomikos.datasource.primary.xa-properties.url=jdbc:mysql://127.0.0.1:3306/jtaSpringBoot?characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&serverTimezone=UTC
+spring.jta.atomikos.datasource.primary.xa-properties.user=root
+spring.jta.atomikos.datasource.primary.xa-properties.password=5608095liyukun
+spring.jta.atomikos.datasource.primary.xa-data-source-class-name=com.mysql.cj.jdbc.MysqlXADataSource
+spring.jta.atomikos.datasource.primary.unique-resource-name=test1
+spring.jta.atomikos.datasource.primary.max-pool-size=25
+spring.jta.atomikos.datasource.primary.min-pool-size=3
+spring.jta.atomikos.datasource.primary.max-lifetime=20000
+spring.jta.atomikos.datasource.primary.borrow-connection-timeout=10000
+
+spring.jta.atomikos.datasource.secondary.xa-properties.url=jdbc:mysql://127.0.0.1:3306/jtaSpringBootSec?characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&serverTimezone=UTC
+spring.jta.atomikos.datasource.secondary.xa-properties.user=root
+spring.jta.atomikos.datasource.secondary.xa-properties.password=5608095liyukun
+spring.jta.atomikos.datasource.secondary.xa-data-source-class-name=com.mysql.cj.jdbc.MysqlXADataSource
+spring.jta.atomikos.datasource.secondary.unique-resource-name=test2
+spring.jta.atomikos.datasource.secondary.max-pool-size=25
+spring.jta.atomikos.datasource.secondary.min-pool-size=3
+spring.jta.atomikos.datasource.secondary.max-lifetime=20000
+spring.jta.atomikos.datasource.secondary.borrow-connection-timeout=10000

+ 39 - 0
jtaSpringBoot/src/test/java/org/example/Test1.java

@@ -0,0 +1,39 @@
+package org.example;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Assertions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+@SpringBootTest(classes = Main.class)
+public class Test1 {
+
+    @Autowired
+    protected JdbcTemplate primaryJdbcTemplate;
+    @Autowired
+    protected JdbcTemplate secondaryJdbcTemplate;
+
+    @Autowired
+    private TestService testService;
+    @Test
+    public void test1() throws Exception {
+        // 正确更新的情况
+        testService.tx();
+        Assertions.assertEquals(30, primaryJdbcTemplate.queryForObject("select age from user where name=?", Integer.class, "aaa"));
+        Assertions.assertEquals(30, secondaryJdbcTemplate.queryForObject("select age from user where name=?", Integer.class, "aaa"));
+    }
+    @Test
+    public void test2() throws Exception {
+        // 更新失败的情况
+        try {
+            testService.tx2();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            // 部分更新失败,test1中的更新应该回滚
+            Assertions.assertEquals(30, primaryJdbcTemplate.queryForObject("select age from user where name=?", Integer.class, "aaa"));
+            Assertions.assertEquals(30, secondaryJdbcTemplate.queryForObject("select age from user where name=?", Integer.class, "aaa"));
+        }
+    }
+}