最近搭建架构,碰到JTA和事务Transaction的问题,在此做个总结:
架构:Mybatis+ Spring
技术:spring的AbstractRoutingDataSource和JTA
老规矩,先贴代码,在讲原理,刚开始的时候不使用JTA,代码如下:
/**
* DataSource上下文句柄,通过此类设置需要访问的对应数据源
*
*/
public class DataSourceContextHolder {
/**
* DataSource上下文,每个线程对应相应的数据源key
*/
public static final ThreadLocal contextHolder = new ThreadLocal();
public static void setDataSourceType(String dataSourceType)
{
contextHolder.set(dataSourceType);
}
public static String getDataSourceType()
{
return contextHolder.get();
}
public static void clearDataSourceType()
{
contextHolder.remove();
}
}
/**
* 动态数据源
*
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSourceType();
}
}
spring中配置如下:
<!-- 配置数据源 -->
<bean id="ds1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
lazy-init="false">
<property name="driverClassName" value="${jdbc.ds1.driverClassName}" />
<property name="url" value="${jdbc.ds1.url}" />
<property name="username" value="${jdbc.ds1.username}" />
<property name="password" value="${jdbc.ds1.password}" />
<property name="initialSize" value="5" />
<property name="maxActive" value="10" />
<property name="maxWait" value="60000" />
<property name="poolPreparedStatements" value="true" />
</bean>
<bean id="ds2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
lazy-init="false">
<property name="driverClassName" value="${jdbc.ds2.driverClassName}" />
<property name="url" value="${jdbc.ds2.url}" />
<property name="username" value="${jdbc.ds2.username}" />
<property name="password" value="${jdbc.ds2.password}" />
<property name="initialSize" value="5" />
<property name="maxActive" value="10" />
<property name="maxWait" value="60000" />
<property name="poolPreparedStatements" value="true" />
</bean>
<!-- 动态数据源 -->
<bean id="dataSource" class="xxx.DynamicDataSource">
<property name="targetDataSources">
<map>
<entry key="ds1" value-ref="ds1" />
<entry key="ds2" value-ref="ds2" />
</map>
</property>
<property name="defaultTargetDataSource" ref="ds1" />
</bean>
<!-- 事务管理 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven/>
<!-- myBatis配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
<!-- DAO层由 MapperScannerConfigurer自动生成mapper bean -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="xxx.mapper" />
</bean>
因为每个Service目前只可能访问一个DataSource,所以在调用Service的时候,调用DataSourceContextHolder.setDataSourceType(key)(key可以为ds1,ds2),
就可以动态切换数据源了(当然最好用AOP思想,技术上spring + AspectJ,在每个Service需要的方法切上一刀),
而且对于spring的@Transactional事务管理是起作用的
OK,按照这种模式,如果Service可能访问多个库,就将DataSourceTransactionManager换成JtaTransactionManager
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager" />
<tx:annotation-driven transaction-manager="transactionManager" />
当然,Datasource换成JNDI获取
<!-- 创建数据源。 -->
<bean id="ds1" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>ds1</value>
</property>
<property name="resourceRef">
<value>true</value>
</property>
</bean>
<bean id="ds2" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>ds2</value>
</property>
<property name="resourceRef">
<value>true</value>
</property>
</bean>
在spring的@Transactional事务管理中,那是死活无法切换数据源
由于内容有点多,这个技术总结分为两部分。
分享到:
相关推荐
springboot + mybatis-plus + database+ 多数据源 + redis + hutool 框架干净,没有其他冗余的成分; 配置了MP的代码生成器,意见生成代码,节省开发时间! 可用于各种定时任务处理,各种夸库操作, 多数据源支持...
"Spring3+Hibernate4+Maven+JUnit 多库多数据源实现"是一个典型的Java Web项目配置,它涉及了多个核心技术来处理复杂的数据管理需求。下面将详细阐述这些技术以及如何协同工作以实现多库多数据源。 首先,Spring...
myBatis 多数据源配置就是为了解决这样的问题。myBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。与 Spring Boot 结合使用时,可以方便地管理和切换不同的数据源。 首先,我们要理解什么...
总之,“spring mybatis atomikos 多库分布式事务demo”是一个实践性的教程,帮助开发者掌握如何在分布式环境中,利用Spring和MyBatis结合Atomikos来处理多数据库的事务一致性问题。通过这个示例,我们可以深入理解...
在Spring Boot中,我们可以通过配置不同的数据源来实现这一目标。 1. **配置Spring Boot多数据源**: - 使用`@ConfigurationProperties`注解来定义两个数据源的配置,例如:`application.properties`或`...
1. **配置数据源**:在Spring配置文件中,为每个数据库定义一个数据源,这些数据源可以通过`@Bean`注解创建。每个数据源对应一个特定的数据库连接池,如HikariCP或Druid。 2. **启用Atomikos**:引入Atomikos的依赖...
支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。支持数据库敏感配置信息 加密(可自定义) ENC()。支持每个数据库独立初始化表结构schema和数据库database。支持无数据源启动,支持懒加载...
Spring Boot 整合 MyBatis 使用多数据源的实现方法 本文主要介绍了 Spring Boot 整合 MyBatis 使用多数据源的实现方法,旨在帮助读者了解如何在 Spring Boot 项目中使用多个数据源。下面将详细介绍多数据源的实现...
支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。 支持数据库敏感配置信息 加密(可自定义) ENC()。 支持每个数据库独立初始化表结构schema和数据库database。 支持无数据源启动,支持懒加载...
一个基于springboot的快速集成多数据源的启动器简介dynamic-datasource-spring-boot-starter是一个基于springboot的快速集成多数据源的启动器。其支持Jdk 1.7 +,SpringBoot 1.4.x 1.5.x 2.xx。文件| 文献资料|特性...
4. **动态切换数据源**:在多库环境中,根据业务需求动态切换数据源是常见的需求。Spring框架提供了TransactionManager和AOP机制来支持这一功能。例如,通过@Qualifier注解指定数据源,或者使用...
支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。 支持数据库敏感配置信息 加密(可自定义) ENC()。 支持每个数据库独立初始化表结构schema和数据库database。 支持无数据源启动,支持懒加载...
本文将深入探讨如何利用Spring Integration进行数据库数据的同步,并以`jdbc-inbound`为例进行详细解析。 首先,Spring Integration的核心理念是通过定义通道(Channel)和消息驱动的组件(Message-driven ...
支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。 支持数据库敏感配置信息 加密(可自定义) ENC()。 支持每个数据库独立初始化表结构schema和数据库database。 支持无数据源启动,支持懒加载...
下面将详细介绍如何在Spring Boot中整合多数据源并实现本地分布式事务。 一、多数据源设计 1. **配置多数据源**:Spring Boot允许我们配置多个数据源,通过不同的配置类或YAML/Properties文件来区分。每个数据源...
通过不同的配置文件(如`application-db1.properties`,`application-db2.properties`)可以设定不同的数据库连接信息,Spring Boot会自动识别并加载相应的数据源。 2. **JPA实体(Entities)**:这是ORM的核心,是...
为了解决多库环境下的数据一致性问题,一种常见的解决方案是采用补偿事务机制。补偿事务的核心思想在于:对于每个关键操作,除了定义正向操作外,还需定义相应的逆向操作(即补偿操作),以便在正向操作失败时可以...
通过阅读并分析PageHelper的源代码,例如在GitHub上的pagehelper-fix分支,我们可以深入理解其内部实现机制,包括动态SQL的生成、数据库方言的处理、拦截器的使用等,这对于提升开发技能和优化项目性能都大有裨益。...
例如,当jtaTx事务涉及到多库操作时,由于数据库连接没有根据不同的数据源切换,会抛出“Table 'merchant.orders' doesn't exist”的错误。为了解决这个情况,我们需要对JtaTransactionManager进行扩展,添加一个`...
介绍多库系统和数据库系统的概念、方法、理论