`
jijun87120681
  • 浏览: 41292 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

多库数据源深入分析(Mybatis+ Spring + JTA)(一)

    博客分类:
  • java
阅读更多

 

最近搭建架构,碰到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事务管理中,那是死活无法切换数据源

 

由于内容有点多,这个技术总结分为两部分。

 

 

 

4
1
分享到:
评论
3 楼 bluesky4485 2014-07-24  
这种方式只能在调用services之前,在controller里面切换才行
2 楼 caohaihua 2013-08-12  
亲,多数据源切换好像不行哦,AbstractRoutingDataSource 加载的时候就会去调用的,能加个qq吗:1205988825,谢谢
1 楼 ff861 2013-07-30  
亲,想问下这个问题您最终是怎么解决的呢?我现在也遇到这个问题啊。

相关推荐

    springboot + mybatis-plus + oracle + 多数据源 + redis + hutool

    springboot + mybatis-plus + database+ 多数据源 + redis + hutool 框架干净,没有其他冗余的成分; 配置了MP的代码生成器,意见生成代码,节省开发时间! 可用于各种定时任务处理,各种夸库操作, 多数据源支持...

    spring3+hibernate4+maven+junit 多库多数据源实现

    "Spring3+Hibernate4+Maven+JUnit 多库多数据源实现"是一个典型的Java Web项目配置,它涉及了多个核心技术来处理复杂的数据管理需求。下面将详细阐述这些技术以及如何协同工作以实现多库多数据源。 首先,Spring...

    myBatis多数据源配置

    myBatis 多数据源配置就是为了解决这样的问题。myBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。与 Spring Boot 结合使用时,可以方便地管理和切换不同的数据源。 首先,我们要理解什么...

    spring mybatis atomikos 多库分布式事务demo

    总之,“spring mybatis atomikos 多库分布式事务demo”是一个实践性的教程,帮助开发者掌握如何在分布式环境中,利用Spring和MyBatis结合Atomikos来处理多数据库的事务一致性问题。通过这个示例,我们可以深入理解...

    springboot多数据源切换mysql+sql server事例

    在Spring Boot中,我们可以通过配置不同的数据源来实现这一目标。 1. **配置Spring Boot多数据源**: - 使用`@ConfigurationProperties`注解来定义两个数据源的配置,例如:`application.properties`或`...

    纯spring多库

    1. **配置数据源**:在Spring配置文件中,为每个数据库定义一个数据源,这些数据源可以通过`@Bean`注解创建。每个数据源对应一个特定的数据库连接池,如HikariCP或Druid。 2. **启用Atomikos**:引入Atomikos的依赖...

    基于 SpringBoot 多数据源 动态数据源 主从分离 快速启动器 支持分布式事务

    支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。支持数据库敏感配置信息 加密(可自定义) ENC()。支持每个数据库独立初始化表结构schema和数据库database。支持无数据源启动,支持懒加载...

    Spring Boot 整合mybatis 使用多数据源的实现方法

    Spring Boot 整合 MyBatis 使用多数据源的实现方法 本文主要介绍了 Spring Boot 整合 MyBatis 使用多数据源的实现方法,旨在帮助读者了解如何在 Spring Boot 项目中使用多个数据源。下面将详细介绍多数据源的实现...

    基于 SpringBoot的多数据源 动态数据源 主从分离 快速启动器 支持分布式事务

    支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。 支持数据库敏感配置信息 加密(可自定义) ENC()。 支持每个数据库独立初始化表结构schema和数据库database。 支持无数据源启动,支持懒加载...

    dynamic-datasource-spring-boot-starter:springboot的动态数据源多数据源动态数据源主从分离读写分离分布式事务https:dynamic-datasource.com

    一个基于springboot的快速集成多数据源的启动器简介dynamic-datasource-spring-boot-starter是一个基于springboot的快速集成多数据源的启动器。其支持Jdk 1.7 +,SpringBoot 1.4.x 1.5.x 2.xx。文件| 文献资料|特性...

    分库代码(备份库、建库,动态创建数据源、动态切换数据源)

    4. **动态切换数据源**:在多库环境中,根据业务需求动态切换数据源是常见的需求。Spring框架提供了TransactionManager和AOP机制来支持这一功能。例如,通过@Qualifier注解指定数据源,或者使用...

    dynamic-datasource-spring-boot-starter-v3.5.1.zip

    支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。 支持数据库敏感配置信息 加密(可自定义) ENC()。 支持每个数据库独立初始化表结构schema和数据库database。 支持无数据源启动,支持懒加载...

    spring integration同步数据库数据

    本文将深入探讨如何利用Spring Integration进行数据库数据的同步,并以`jdbc-inbound`为例进行详细解析。 首先,Spring Integration的核心理念是通过定义通道(Channel)和消息驱动的组件(Message-driven ...

    dynamic-datasource-spring-boot-starter-v3.5.1.tar.gz

    支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。 支持数据库敏感配置信息 加密(可自定义) ENC()。 支持每个数据库独立初始化表结构schema和数据库database。 支持无数据源启动,支持懒加载...

    SpringBoot整合多数据源,并实现本地分布式事务

    下面将详细介绍如何在Spring Boot中整合多数据源并实现本地分布式事务。 一、多数据源设计 1. **配置多数据源**:Spring Boot允许我们配置多个数据源,通过不同的配置类或YAML/Properties文件来区分。每个数据源...

    spring boot 常用数据库操作例子

    通过不同的配置文件(如`application-db1.properties`,`application-db2.properties`)可以设定不同的数据库连接信息,Spring Boot会自动识别并加载相应的数据源。 2. **JPA实体(Entities)**:这是ORM的核心,是...

    多库多事务降低数据不一致概率

    为了解决多库环境下的数据一致性问题,一种常见的解决方案是采用补偿事务机制。补偿事务的核心思想在于:对于每个关键操作,除了定义正向操作外,还需定义相应的逆向操作(即补偿操作),以便在正向操作失败时可以...

    Mybatis分页插件 - PageHelper.zip

    通过阅读并分析PageHelper的源代码,例如在GitHub上的pagehelper-fix分支,我们可以深入理解其内部实现机制,包括动态SQL的生成、数据库方言的处理、拦截器的使用等,这对于提升开发技能和优化项目性能都大有裨益。...

    Atomikos jta事务框架改写历程

    例如,当jtaTx事务涉及到多库操作时,由于数据库连接没有根据不同的数据源切换,会抛出“Table 'merchant.orders' doesn't exist”的错误。为了解决这个情况,我们需要对JtaTransactionManager进行扩展,添加一个`...

    多库系统与数据集成技术

    介绍多库系统和数据库系统的概念、方法、理论

Global site tag (gtag.js) - Google Analytics