springboot+jta+atomikos分布式多数据源事务管理 (SQLserver)

简介: 在我上一篇博客的项目基础上做更改springboot多数据源分包式实现首先我们来试一下没有更改的情况下

在我上一篇博客的项目基础上做更改

springboot多数据源分包式实现

首先我们来试一下没有更改的情况下

1.@Service
public class User2Service {
  @Autowired
  private User2Mapper mapper2;
  @Autowired
  private User2Mapper mapper1;
  @Transactional
  public void insert() {
    mapper1.insert();
    int a = 1/0;
    mapper2.insert();
  }
}
@Repository
public interface User1Mapper{
  @Insert("insert into user_demo values('事务管理','1')")
  public void insert();
}
@Repository
public interface User2Mapper {
  @Insert("insert into user_demo values('事务管理','2')")
  public void insert();
}

在User2Service中同时对User1Mapper 和User2Mapper进行事务管理,在中间的除零异常出现后,数据还是被保存到了数据库,但是只是UserMapper2的数据被保存到了数据库,UserMapper1的数据被回滚,这种情况下默认是只对@Primary的数据源进行事务管理



那我们就把事务管理交给atomikos


首先application.properties配置文件重新写一下,依赖引入一下

sqlserver.datasource.test1.url=jdbc:sqlserver://localhost:1433;DatabaseName=Test
sqlserver.datasource.test1.username=sa
sqlserver.datasource.test1.password=vhukze
sqlserver.datasource.test1.minPoolSize=3
sqlserver.datasource.test1.maxPoolSize=25
sqlserver.datasource.test1.maxLifetime=20000
sqlserver.datasource.test1.borrowConnectionTimeout=30
sqlserver.datasource.test1.loginTimeout=30
sqlserver.datasource.test1.maintenanceInterval=60
sqlserver.datasource.test1.maxIdleTime=60
sqlserver.datasource.test1.testQuery=select 1
#mybatis  配置文件
#sqlserver.datasource.test1.mapper-locations=classpath:mapper1/*.xml
#mybatis 对应的实体类
#sqlserver.datasource.test1.type-aliases-package=com.wangye.spbootjtaautomatic.model1
#sqlserver2
sqlserver.datasource.test2.url=jdbc:sqlserver://localhost:1433;DatabaseName=Test1
sqlserver.datasource.test2.username=sa
sqlserver.datasource.test2.password=vhukze
sqlserver.datasource.test2.minPoolSize=3
sqlserver.datasource.test2.maxPoolSize=25
sqlserver.datasource.test2.maxLifetime=20000
sqlserver.datasource.test2.borrowConnectionTimeout=30
sqlserver.datasource.test2.loginTimeout=30
sqlserver.datasource.test2.maintenanceInterval=60
sqlserver.datasource.test2.maxIdleTime=60
sqlserver.datasource.test2.testQuery=select 1
#mybatis  配置文件
#sqlserver.datasource.test2.mapper-locations=classpath:mapper2/*.xml
#mybatis 对应的实体类
#sqlserver.datasource.test2.type-aliases-package=com.wangye.spbootjtaautomatic.model2
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>

我这里没有建实体类也没有用配置文件 。

然后把之前的数据源配置类注释了 删了也行 我这里就注释了。

新建两个配置类

package com.vhukze.datasource;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.microsoft.sqlserver.jdbc.SQLServerXADataSource;
import com.vhukze.config.DBConfig1;
/**
* @author zsz
* @version 
* @创建时间:2019年9月3日 上午9:31:28
*/
@Configuration
@MapperScan(basePackages="com.vhukze.test1",sqlSessionTemplateRef="test1SqlSessionTemplate")
public class TestMybatisConfig1 {
  @Primary
  @Bean(name="test1DataSource")
  public DataSource testDataSource(DBConfig1 testConfig) throws SQLException {
    SQLServerXADataSource sqlServerXADataSource = new SQLServerXADataSource();
    sqlServerXADataSource.setURL(testConfig.getUrl());
    sqlServerXADataSource.setUser(testConfig.getUsername());
    sqlServerXADataSource.setPassword(testConfig.getPassword());
    AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
    atomikosDataSourceBean.setXaDataSource(sqlServerXADataSource);
    atomikosDataSourceBean.setUniqueResourceName("test1DataSource");
    atomikosDataSourceBean.setMinPoolSize(testConfig.getMinPoolSize());
    atomikosDataSourceBean.setMaxPoolSize(testConfig.getMaxPoolSize());
    atomikosDataSourceBean.setMaxLifetime(testConfig.getMaxLifeTime());
    atomikosDataSourceBean.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeOut());
    atomikosDataSourceBean.setLoginTimeout(testConfig.getLoginTimeOut());
    atomikosDataSourceBean.setMaintenanceInterval(testConfig.getMaintenanceInterval());
    atomikosDataSourceBean.setMaxIdleTime(testConfig.getMaxIdleTime());
    atomikosDataSourceBean.setTestQuery(testConfig.getTestQuery());
    return atomikosDataSourceBean;
  }
  @Bean(name="test1SqlSessionFactory")
  public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource) throws Exception { 
    SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    return bean.getObject();
  }
  @Bean(name="test1SqlSessionTemplate")
  public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) { 
    return new SqlSessionTemplate(sqlSessionFactory);
  }
}

第二个就把这里面的test1和DBConfig1改成test2和DBConfig2 就好了,跟之前的配置类差不多,就是把DataSource交给atomikos管理了

然后创建一下里面需要用到的配置实体类DBConfig1和DBConfig2 在新建的一个config包下

package com.vhukze.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author zsz
* @version 
* @创建时间:2019年9月3日 上午9:55:23
*/
@ConfigurationProperties(prefix="sqlserver.datasource.test1")
public class DBConfig1 {
  private String url;
  private String username;
  private String password;
  private int minPoolSize;
  private int maxPoolSize;
  private int maxLifeTime;
  private int borrowConnectionTimeOut;
  private int loginTimeOut;
  private int maintenanceInterval;
  private int maxIdleTime;
  private String testQuery;
  get set 方法
}

这个跟上面一样    DBConfig2 就把注解里面的test1改成test2

在启动类添加扫描config包 还有一个什么开启配置文件 就把两个字节码文件给它就行

1.@SpringBootApplication
@ComponentScan(basePackages= {"com.vhukze.config","com.vhukze.controller","com.vhukze.test1.service","com.vhukze.test2.service","com.vhukze.datasource"})
@MapperScan({"com.vhukze.test1.mapper","com.vhukze.test2.mapper"})
@EnableConfigurationProperties(value = {DBConfig1.class,DBConfig2.class})
public class App {
  public static void main(String[] args) {
    SpringApplication.run(App.class, args);
  }
}

到这里就改完了配置,也没多麻烦。


启动项目访问映射路径------报错……


无法创建 XA 控制连接。错误:“找不到存储过程 'master..xp_sqljdbc_xa_init_ex'


这是因为sql server库的服务器没有配置XA事务和安装JDBC插件


解决步骤写在了另一篇博客中-->无法创建XA控制连接


而且我之前用的是公司服务器中的SQLserver,然后换成本机的了,但是不知道连接密码,解决办法


-->SQLserver改登录密码


都弄好之后测试成功,可以同时管理两个数据源的事务


相关文章
|
9月前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
801 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
|
NoSQL Java Redis
Springboot使用Redis实现分布式锁
通过这些步骤和示例,您可以系统地了解如何在Spring Boot中使用Redis实现分布式锁,并在实际项目中应用。希望这些内容对您的学习和工作有所帮助。
1453 83
|
存储 Java 关系型数据库
在Spring Boot中整合Seata框架实现分布式事务
可以在 Spring Boot 中成功整合 Seata 框架,实现分布式事务的管理和处理。在实际应用中,还需要根据具体的业务需求和技术架构进行进一步的优化和调整。同时,要注意处理各种可能出现的问题,以保障分布式事务的顺利执行。
1548 160
|
监控 Java 调度
SpringBoot中@Scheduled和Quartz的区别是什么?分布式定时任务框架选型实战
本文对比分析了SpringBoot中的`@Scheduled`与Quartz定时任务框架。`@Scheduled`轻量易用,适合单机简单场景,但存在多实例重复执行、无持久化等缺陷;Quartz功能强大,支持分布式调度、任务持久化、动态调整和失败重试,适用于复杂企业级需求。文章通过特性对比、代码示例及常见问题解答,帮助开发者理解两者差异,合理选择方案。记住口诀:单机简单用注解,多节点上Quartz;若是任务要可靠,持久化配置不能少。
1080 4
|
存储 Java 文件存储
🗄️Spring Boot 3 整合 MinIO 实现分布式文件存储
本文介绍了如何基于Spring Boot 3和MinIO实现分布式文件存储。随着应用规模扩大,传统的单机文件存储方案难以应对大规模数据和高并发访问,分布式文件存储系统成为更好的选择。文章详细讲解了MinIO的安装、配置及与Spring Boot的整合步骤,包括Docker部署、MinIO控制台操作、Spring Boot项目中的依赖引入、配置类编写及工具类封装等内容。最后通过一个上传头像的接口示例展示了具体的开发和测试过程,强调了将API操作封装成通用工具类以提高代码复用性和可维护性的重要性。
2876 7
🗄️Spring Boot 3 整合 MinIO 实现分布式文件存储
|
缓存 NoSQL Java
Spring Boot中的分布式缓存方案
Spring Boot提供了简便的方式来集成和使用分布式缓存。通过Redis和Memcached等缓存方案,可以显著提升应用的性能和扩展性。合理配置和优化缓存策略,可以有效避免常见的缓存问题,保证系统的稳定性和高效运行。
507 3
|
Java 数据库连接
SpringBoot配置多数据源实战
第四届光学与机器视觉国际学术会议(ICOMV 2025) 2025 4th International Conference on Optics and Machine Vision
962 8
|
Java 微服务 Spring
SpringBoot+Vue+Spring Cloud Alibaba 实现大型电商系统【分布式微服务实现】
文章介绍了如何利用Spring Cloud Alibaba快速构建大型电商系统的分布式微服务,包括服务限流降级等主要功能的实现,并通过注解和配置简化了Spring Cloud应用的接入和搭建过程。
SpringBoot+Vue+Spring Cloud Alibaba 实现大型电商系统【分布式微服务实现】
|
运维 NoSQL Java
SpringBoot接入轻量级分布式日志框架GrayLog技术分享
在当今的软件开发环境中,日志管理扮演着至关重要的角色,尤其是在微服务架构下,分布式日志的统一收集、分析和展示成为了开发者和运维人员必须面对的问题。GrayLog作为一个轻量级的分布式日志框架,以其简洁、高效和易部署的特性,逐渐受到广大开发者的青睐。本文将详细介绍如何在SpringBoot项目中接入GrayLog,以实现日志的集中管理和分析。
1363 1