spring 多数据源 JTA 事务管理

 一、pom.xml里添加


		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jta-atomikos</artifactId>
			<version>2.6.6</version>
		</dependency>

 二、添加TransactionManagerConfig.class

package org.jeecg.modules.wms.config;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
import org.springframework.context.annotation.*;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.jta.JtaTransactionManager;

import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;

@Configuration
@ComponentScan
@EnableTransactionManagement
public class TransactionManagerConfig {
    @Bean(name = "userTransaction")
    public UserTransaction userTransaction() throws Throwable {
        UserTransactionImp userTransactionImp = new UserTransactionImp();
        return userTransactionImp;
    }

    @Bean(name = "atomikosTransactionManager")
    public TransactionManager atomikosTransactionManager() throws Throwable {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        userTransactionManager.setForceShutdown(false);
        return userTransactionManager;
    }

    @Bean(name = "jta-transaction-manager")
    @DependsOn({"userTransaction", "atomikosTransactionManager"})
    @Primary
    public PlatformTransactionManager transactionManager() throws Throwable {
        return new JtaTransactionManager(userTransaction(), atomikosTransactionManager());
    }
}

三、添加 DynamicDataSourceProviderImpl.class

package org.jeecg.modules.wms.config;

import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.mysql.cj.jdbc.MysqlXADataSource;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;


@Service
@Primary
public class DynamicDataSourceProviderImpl implements DynamicDataSourceProvider {
    /**
     * 配置文件数据的松散绑定
     */
    private final DynamicDataSourceProperties properties;

    public DynamicDataSourceProviderImpl(DynamicDataSourceProperties properties) {
        this.properties = properties;
    }

    @Override
    public Map<String, DataSource> loadDataSources() {
        Map<String, DataSourceProperty> dataSourcePropertiesMap = properties.getDatasource();
        Map<String, DataSource> dataSourceMap = new HashMap<>(dataSourcePropertiesMap.size() * 2);
        for (Map.Entry<String, DataSourceProperty> item : dataSourcePropertiesMap.entrySet()) {
            String poolName = item.getKey();
            DataSourceProperty dataSourceProperty = item.getValue();
            dataSourceProperty.setPoolName(poolName);
            // 接受数据源配置 并创建AtomikosDataSourceBean
            dataSourceMap.put(poolName, createDataSource(dataSourceProperty));
        }
        return dataSourceMap;
    }

    /**
     * 创建数据源
     *
     * @param dataSourceProperty 数据源信息
     * @return 数据源
     */
    private DataSource createDataSource(DataSourceProperty dataSourceProperty) {
        MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
        mysqlXaDataSource.setUrl(dataSourceProperty.getUrl());
        mysqlXaDataSource.setPassword(dataSourceProperty.getPassword());
        mysqlXaDataSource.setUser(dataSourceProperty.getUsername());
        AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
        xaDataSource.setXaDataSource(mysqlXaDataSource);
        xaDataSource.setMinPoolSize(5);
        xaDataSource.setBorrowConnectionTimeout(60);
        xaDataSource.setMaxPoolSize(20);
        xaDataSource.setXaDataSourceClassName(dataSourceProperty.getDriverClassName());
        xaDataSource.setTestQuery("SELECT 1 FROM DUAL");
        xaDataSource.setUniqueResourceName(dataSourceProperty.getPoolName());
        return xaDataSource;
    }
}

四、应用

在需要管理多数据源事务的方法上使用@Transactional注解时,搭配上transactionManager = "jta-transaction-manager",其中的jta-transaction-manager是PlatformTransactionManager 对象注入为Bean时的name值,相关代码在TransactionManagerConfig.class中

	// 多数据源事务处理
	@Override
	@Transactional(rollbackFor = Exception.class, transactionManager = "jta-transaction-manager")
	public Boolean xxxxx(Integer orderId, Integer orderStatus) {...}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring+iBatis+JOTM实现JTA事务: 如何处理跨库事物:spring + jtom 的jta事务是个很好的选择. 这个源码示例非常不错,包括所有的源码和jar包,下载后eclipse 或 myeclipse 导入就能用。 里面有详细的说明和注释,欢迎下载传播。有问题请在评价中留言,我会及时回复的。 <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/> <!-- JTA事务管理器 --> <bean id="myJtaManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="userTransaction"> <ref local="jotm"/> </property> </bean> <!-- 数据源A --> <bean id="dataSourceA" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"> <property name="dataSource"> <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"> <property name="transactionManager" ref="jotm"/> <property name="driverName" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> </bean> </property> <property name="user" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- 数据源B --> <bean id="dataSourceB" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"> <property name="dataSource"> <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown"> <property name="transactionManager" ref="jotm"/> <property name="driverName" value="${jdbc2.driver}"/> <property name="url" value="${jdbc2.url}"/> </bean> </property> <property name="user" value="${jdbc2.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- 事务切面配置 --> <aop:config> <aop:pointcut id="serviceOperation" expression="execution(* *..servi1ce*..*(..))"/> <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice"/> </aop:config> <!-- 通知配置 --> <tx:advice id="txAdvice" transaction-manager="myJtaManager"> <tx:attributes> <tx:method name="delete*" rollback-for="Exception"/> <tx:method name="save*" rollback-for="Exception"/> <tx:method name="update*" rollback-for="Exception"/> <tx:method name="*" read-only="true" rollback-for="Exception"/> </tx:attributes> </tx:advice ...... ...... ......
Java中,如果你需要在多个数据源中执行同一事务,你可以使用分布式事务处理框架来实现。这些框架可以根据需要将多个数据库操作包装在同一个事务中,并确保在所有操作完成之前,事务要么全部提交,要么全部回滚。 一种常见的分布式事务处理框架是Spring Framework。在Spring中,你可以使用`@Transactional`注解来标记需要在同一事务中执行的方法。在这种情况下,如果你使用了多个数据源,则需要使用JTAJava Transaction API)来协调这些数据源。 具体地,你需要在应用程序中配置一个JTA事务管理器,并在每个数据源上配置一个XA数据源。然后,你可以使用@Transactional注解来标记需要在同一事务中执行的方法,Spring将自动使用JTA协调事务。 例如,以下示例演示了如何使用Spring和Atomikos JTA实现多线程多数据源保证同一事务: ```java @Service public class MyService { @Autowired private PlatformTransactionManager transactionManager; @Transactional public void doSomething() { // ... 执行数据库操作1 ... // ... 执行数据库操作2 ... } public void doSomethingInMultipleThreads() { Executor executor = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { executor.execute(() -> { TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); transactionTemplate.execute(status -> { // ... 执行数据库操作1 ... }); transactionTemplate.execute(status -> { // ... 执行数据库操作2 ... }); }); } } } ``` 在这个例子中,`MyService`类中的`doSomething()`方法和`doSomethingInMultipleThreads()`方法都被标记为@Transactional。`doSomething()`方法只是一个简单的事务方法,它执行两个数据库操作。`doSomethingInMultipleThreads()`方法则启动了10个线程,每个线程都执行相同的两个数据库操作。由于这些操作都在同一个事务中执行,因此它们要么全部提交,要么全部回滚。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值