使用JTA Atomikos管理分布式事务[Druid连接池]

741 阅读2分钟

编写

application.properties相关编写在最下面

使用druid数据库连接池和连接多个数据源

从数据源的写法同上,与之前不同的是在注入进IOCDatasource对象是AtomikosDataSourceBean类型的,Mybatis-Plus的sqlSessionFactory也要使用MybatisSqlSessionFactoryBean (巨坑) 注:高版本mysql driver中的接口com.mysql.cj.conf.PropertySet不存在getBooleanReadableProperty方法,所以请使用MySQL8.0.11版本要不然会报空指针异常。

@Configuration
@EnableConfigurationProperties
@EnableTransactionManagement(proxyTargetClass = true)
public class DatasourceConfig {
    //db properties prefix
    final static String DB1_PREFIX = "spring.jta.atomikos.datasource.db1";
    final static String DB2_PREFIX = "spring.jta.atomikos.datasource.db2";
    final static Logger logger = LoggerFactory.getLogger(DatasourceConfig.class);

    /**
     * 添加数据源
     */
    @Primary
    @Bean(name = "db1Datasource")
    @ConfigurationProperties(prefix = DB1_PREFIX)
    public DataSource db1Datasource() {
        return new AtomikosDataSourceBean();
    }

    @Bean(name = "db2Datasource")
    @ConfigurationProperties(prefix = DB2_PREFIX)
    public DataSource db2Datasource() {
        return new AtomikosDataSourceBean();
    }
}
@Configuration
@MapperScan(basePackages = DB1DatasourceConfig.PACKAGE,
        sqlSessionFactoryRef = "db1sqlSessionFactory",
        sqlSessionTemplateRef = "db1sqlSessionTemplate"

)
public class DB1DatasourceConfig {
    public final static String PACKAGE = "com.demo.prademo.mapper.DB1";
    public final static String MAPPER_LOCATION = "classpath:mappers/DB1/*xml";
    public DataSource db1Datasource;


    public DB1DatasourceConfig(@Qualifier("db1Datasource") DataSource db1Datasource) {
        this.db1Datasource = db1Datasource;
    }

    @Bean
    @Primary
    public SqlSessionFactory db1sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(db1Datasource);
        sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));
        return sqlSessionFactory.getObject();
    }

    @Bean
    @Primary
    public SqlSessionTemplate db1sqlSessionTemplate() throws Exception {
        return new SqlSessionTemplate(db1sqlSessionFactory());
    }
}
# 应用名称
spring.application.name=Prademo
# 应用服务 WEB 访问端口
server.port=8080
# 数据库驱动:
# THYMELEAF (ThymeleafAutoConfiguration)
# 开启模板缓存(默认值: true )
spring.thymeleaf.cache=true
# 检查模板是否存在,然后再呈现
spring.thymeleaf.check-template=true
# 检查模板位置是否正确(默认值 :true )
spring.thymeleaf.check-template-location=true
#Content-Type 的值(默认值: text/html )
spring.thymeleaf.content-type=text/html
# 开启 MVC Thymeleaf 视图解析(默认值: true )
spring.thymeleaf.enabled=true
# 模板编码
spring.thymeleaf.encoding=UTF-8
# 要被排除在解析之外的视图名称列表,⽤逗号分隔
spring.thymeleaf.excluded-view-names=
# 要运⽤于模板之上的模板模式。另⻅ StandardTemplate-ModeHandlers( 默认值: HTML5)
spring.thymeleaf.mode=HTML5
# 在构建 URL 时添加到视图名称前的前缀(默认值: classpath:/templates/ )
spring.thymeleaf.prefix=classpath:/templates/
# 在构建 URL 时添加到视图名称后的后缀(默认值: .html )
spring.thymeleaf.suffix=.html
mybatis-plus.config-location=classpath:mybatis/mybatis-config.xml
spring.jta.enabled=true
##Spring表数据库配置
spring.jta.atomikos.datasource.db1.max-pool-size=25
spring.jta.atomikos.datasource.db1.min-pool-size=3
spring.jta.atomikos.datasource.db1.max-lifetime=20000
spring.jta.atomikos.datasource.db1.borrow-connection-timeout=10000
spring.jta.atomikos.datasource.db1.unique-resource-name=db1
spring.jta.atomikos.datasource.db1.xa-properties.url=jdbc:mysql://localhost:3306/demodb1?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
spring.jta.atomikos.datasource.db1.xa-properties.username=root
spring.jta.atomikos.datasource.db1.xa-properties.password=123456
spring.jta.atomikos.datasource.db1.xa-properties.driverClassName=com.mysql.cj.jdbc.Driver
spring.jta.atomikos.datasource.db1.xa-data-source-class-name=com.alibaba.druid.pool.xa.DruidXADataSource
# 初始化大小,最小,最大
spring.jta.atomikos.datasource.db1.xa-properties.initialSize=10
spring.jta.atomikos.datasource.db1.xa-properties.minIdle=20
spring.jta.atomikos.datasource.db1.xa-properties.maxActive=100
## 配置获取连接等待超时的时间
spring.jta.atomikos.datasource.db1.xa-properties.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.jta.atomikos.datasource..db1.xa-properties.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.jta.atomikos.datasource.db1.xa-properties.minEvictableIdleTimeMillis=300000
spring.jta.atomikos.datasource.db1.xa-properties.testWhileIdle=true
spring.jta.atomikos.datasource.db1.xa-properties.testOnBorrow=false
spring.jta.atomikos.datasource.db1.xa-properties.testOnReturn=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.jta.atomikos.datasource.db1.xa-properties.poolPreparedStatements=true
spring.jta.atomikos.datasource.db1.xa-properties.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.jta.atomikos.datasource.db1.xa-properties.filters=stat,slf4j,wall
#----
spring.jta.atomikos.datasource.db2.max-pool-size=25
spring.jta.atomikos.datasource.db2.min-pool-size=3
spring.jta.atomikos.datasource.db2.max-lifetime=20000
spring.jta.atomikos.datasource.db2.borrow-connection-timeout=10000
spring.jta.atomikos.datasource.db2.unique-resource-name=db2
spring.jta.atomikos.datasource.db2.xa-properties.url=jdbc:mysql://localhost:3306/demodb2?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
spring.jta.atomikos.datasource.db2.xa-properties.username=root
spring.jta.atomikos.datasource.db2.xa-properties.password=123456
spring.jta.atomikos.datasource.db2.xa-properties.driverClassName=com.mysql.cj.jdbc.Driver
spring.jta.atomikos.datasource.db2.xa-data-source-class-name=com.alibaba.druid.pool.xa.DruidXADataSource
# 初始化大小,最小,最大
spring.jta.atomikos.datasource.db2.xa-properties.initialSize=10
spring.jta.atomikos.datasource.db2.xa-properties.minIdle=20
spring.jta.atomikos.datasource.db2.xa-properties.maxActive=100
## 配置获取连接等待超时的时间
spring.jta.atomikos.datasource.db2.xa-properties.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.jta.atomikos.datasource.db2.xa-properties.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.jta.atomikos.datasource.db2.xa-properties.minEvictableIdleTimeMillis=300000
spring.jta.atomikos.datasource.db2.xa-properties.testWhileIdle=true
spring.jta.atomikos.datasource.db2.xa-properties.testOnBorrow=false
spring.jta.atomikos.datasource.db2.xa-properties.testOnReturn=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.jta.atomikos.datasource.db2.xa-properties.poolPreparedStatements=true
spring.jta.atomikos.datasource.db2.xa-properties.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.jta.atomikos.datasource.db2.xa-properties.filters=stat,slf4j,wall
logging.level.com.demo.prademo.mapper=debug
spring.datasource.druid.filter.wall.config.show-allow=true
mybatis-plus.configuration.cache-enabled=true

测试

估计在其一个数据库插入时中抛出个空指针异常,测试下另外一个是否一起回滚

@Transactional
@GetMapping("/test/insert")
public User insert() {
    db1Service.UserInsert(new User(9999, "test999"));
    db2Service.insert(new Wiki(9999, "test999"));

    if (ObjectUtils.isEmpty(db1Service.selectById(9998))) {
        throw new NullPointerException();
    }
    return db1Service.selectById(9998);
}