`

mybatis 多数据源 以及 多数据源切换

 
阅读更多

最近做流程遇到需求:

            一个流程引擎的数据源,所有流程数据都在此数据源

            针对多个系统多个 用户相关数据源

      流程中只保存  用户id,name信息,其数据来源都是从各个用户数据源取得的。

      流程引擎配置不同系统的人员,部门等配置都需要切换用户数据源来取得,而流程引擎的数据源应该一直保持。

所以解决方案应该为: 

           两套sqlSessionFactory          一个专门针对流程引擎使用

                                                         一个专门用于不同用户数据源

           sqlsessionFactory1---->datasource_engine

           sqlsessionFactory2 ------> datasource_business -------->(切换) userDataSource1,userDataSource2

 

1:实现数据源切换

         DynamicDataSourceHolder.java

           

/**
 * 切源数据源实现类
 *
 */
public class DynamicDataSourceHolder {

	private static final ThreadLocal<String> local = new ThreadLocal<String>();
	
	/**
	 * 清空当前数据源
	 */
	public static void clear(){
		local.remove();
	}
	
	/**
	 * 获取当前数据源
	 */
	public static String get(){
		return local.get();
	}
	
	/**
	 * 设置当前数据源
	 */
	public static void set(String source){
		local.set(source);
	}
	
}

 DynamicDataSource.java

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {

	@Override
	protected Object determineCurrentLookupKey() {
		//返回当前数据源
		return DynamicDataSourceHolder.get();
	}

}

    spring配置

  

<bean id="userDataSource1" class="org.springframework.jndi.JndiObjectFactoryBean">
			<property name="jndiName" value="java:comp/env/jdbc/userDataSource1"></property>
		</bean><!-- 用户数据源1  -->
		<!-- 使用jndi数据源需要在web容器配置如下:
			<Resource auth="Container" driverClassName="oracle.jdbc.OracleDriver" 
			maxActive="10" maxIdle="5" maxWait="15000" name="jdbc/userDataSource1"
			password="123456" type="javax.sql.DataSource" url="jdbc:oracle:thin:@localhost:1521:ORCL"
			username="user" />
		 -->
		 <bean id="userDataSource2" class="org.springframework.jndi.JndiObjectFactoryBean">
			<property name="jndiName" value="java:comp/env/jdbc/userDataSource2"></property>
		</bean><!-- 用户数据源2 -->
		
		<bean id="dataSource_business" class="com.xxx.DynamicDataSource">
			<property name="targetDataSources">
				<map key-type="java.lang.String">
					<entry key="userDataSource1" value-ref="userDataSource1"></entry>
					<entry key="userDataSource2" value-ref="userDataSource2"></entry>
				</map>
			</property>
			<property name="defaultTargetDataSource" ref="userDataSource1"></property>
		</bean><!-- 自定义用户路由数据源 -->
		
		<bean id="dataSource_engine" class="org.springframework.jndi.JndiObjectFactoryBean">
			<property name="jndiName" value="java:comp/env/jdbc/engine"></property>
		</bean><!-- 流程引擎数据源 -->

 使用此种方式  切源数据源的话只需要设置代码:DynamicDataSourceHolder.set(“userDataSource1”);//将用户数据源切换为key为userDataSource1的数据源

 如何动态切换呢?

   可以使用aop来实现     aop拦截相应方法      动态获取key,更改数据源

 比如

  DataSourceAopProxy.java

 

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Service;

/**
 *  aop实现动态切换数据源
 *
 */
@Aspect
@Service
public class DataSourceAopProxy {

	@Pointcut("execution(* com.xxx.*.*(..))")
	private void setDataSource(JoinPoint jp){
		//此处进行切换数据源   根据业务条件   获取数据源id
		String dataSourceName = "userDataSource1";
		DynamicDataSourceHolder.set(dataSourceName);
	}
	
//	@Before("setDataSource()")
//	public void setDataSourceBefore(){
//		String dataSourceName = "before";
//		DynamicDataSourceHolder.set(dataSourceName);
//	}
//	
//	
//	@After("setDataSource()")
//	public void setDataSourceAfter(JoinPoint jp){
//		String dataSourceName = "after";
//		DynamicDataSourceHolder.set(dataSourceName);
//	}
	
}

 不过上面没有具体获取数据源key的方式:

      我的想法是         1 从切面的方法参数中取  (不过好像只能取来参数值,而取不到参数名称,再者也不一定之前写的方法有那个key参数,如果加上的话改动太大太累)

                                2 从session中取。针对各系统用户请求,可以知道系统id,也就可以知道key了。 针对管理员的话,对某个系统管理就需要将sesssion中的key改成此系统的

                                             而且管理员一次只能管理一个系统,而不能管理多个(不同管理员,session不同,可以管理不同系统)

                                      这种方式的话需要把session放入ThreadLocal中,在切面中取session也从threadLocal中取。不过总感觉这个方式太搓

 

 

                            暂时没有别的想法了。

 

2.:两套sqlSessionFactory实现

     

   遇到问题: 系统中用户相关和流程引擎相关实体,mapper都放在一起,分包也不够清晰,做两套sqlSessionFactory的话扫包的basePackage 需要分包

             分包的话各个service引用mapper的地方都要改,工作量太大

  解决:     查看资料发现可以使用自定义注解来取代spring的repository设置到annotationClass中。这样每个mapper文件中注入相应的注解@EngineRepository,@BusinessRepository

<property name="annotationClass" value="org.springframework.stereotype.Repository"></property>

 改成<property name="annotationClass" value="com.xxx.EngineRepository"></property>

  配置文件如下:

   

<bean id="sqlSessionFactory_engine" class="org.mybatis.spring.SqlSessionFactoryBean">
			<property name="configLocation" value="classpath:mybatis_engine.xml"></property>
			<property name="dataSource" ref="dataSource_engine"></property>
			<property name="databaseIdProvider" ref="databaseIdProvider"></property>
		</bean><!-- 流程引擎所用sqlSessionFactory -->
		
		<bean id="sqlSessionFactory_business" class="org.mybatis.spring.SqlSessionFactoryBean">
			<property name="configLocation" value="classpath:mybatis_business.xml"></property>
			<property name="dataSource" ref="dataSource_business"></property>
			<property name="databaseIdProvider" ref="databaseIdProvider"></property>
		</bean><!-- 用户相关sqlSessionFactory -->
		
		<bean id="vendorProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
			<property name="properties">
				<props>
					<prop key="SQL SERVER">sqlserver</prop>
					<prop key="DB2">db2</prop>
					<prop key="Oracle">oracle</prop>
				</props>
			</property>
		</bean>
		
		<bean id="databaseIdProvider" class="org.apache.ibatis.mapping.VendorDatabaseIdProvider">
			<property name="properties" ref="vendorProperties"></property>
		</bean>
		
		
		<bean id="scanner_engine" class="org.mybatis.spring.MapperScannerConfigurer">
			<property name="annotationClass" value="com.xxx.EngineRepository"></property>
			<property name="basePackage" value="com.xxx.*.model"></property>
			<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory_engine"></property>
		</bean><!-- 流程引擎扫mapper配置 -->
		
		<bean id="scanner_business" class="org.mybatis.spring.MapperScannerConfigurer">
			<property name="annotationClass" value="com.xxx.BusinessRepository"></property>
			<property name="basePackage" value="com.xxx.*.model"></property>
			<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory_business"></property>
		</bean><!-- 用户相关扫mapper配置 -->

 

  如上所配置使用流程引擎的mapper文件就加上注解@EngineRepository 

      

// 使用dataSource_engine 数据源
@EngineRepository
public interface TaskAssignMapper {
    TaskAssign getTaskAssignByDeployIdAndTaskKey(String deployId,String taskKey);
    ...
}

// 使用 dataSource_business 数据源
@BusinessRepository
public interface UserDaoMapper {
    List<User> getAllUser();
    ...
}

 

public @interface EngineRepository {
}
public @interface BusinessRepository {
}
分享到:
评论
1 楼 多少青春不再 2016-04-07  
可以请教一下怎样配置一个默认的数据源吗?没有注解就是默认的

相关推荐

    springboot + mybatis 多数据源demo

    在现代企业级应用开发中,...通过灵活的配置和智能的路由策略,开发者可以轻松地处理复杂的数据源切换需求,提升系统的健壮性和可扩展性。实践这个示例,将进一步加深对Spring Boot和MyBatis在实际开发中的理解和运用。

    spring整合mybatis多数据源

    当我们需要处理多个数据源时,例如在分布式系统或读写分离的场景下,Spring整合MyBatis的多数据源切换就显得尤为重要。这个"spring整合mybatis多数据源"的示例提供了可运行的代码,帮助开发者理解和实践这一功能。 ...

    springboot+druid+mybatis多数据源动态切换案例

    8. **测试**:在名为`test`的文件中,可能包含了单元测试或集成测试代码,用于验证多数据源切换和读写分离的正确性。测试用例应该覆盖各种读写操作,确保在不同数据源间的切换无误。 理解并掌握这些知识点,开发者...

    Spring+SpringMVC+Mybatis多数据源

    在企业级应用开发中,Spring、...具体实现时,可以根据项目需求选择合适的方式进行数据源切换,以达到优化性能、提高可扩展性的目的。通过合理配置和设计,可以有效地管理和利用多数据源,提升系统的灵活性和可靠性。

    spring mybatis 多数据源动态切换

    在 `thc-datasources` 压缩包中,可能包含了更详细的配置示例、数据源切换注解的实现以及相关的辅助工具类,如 `DynamicDataSourceContextHolder`。读者可以结合这些资源,进一步理解和实践多数据源动态切换的实现。

    SSM(Spring+SpringMVC+MyBatis)多数据源配置框架

    在多数据源配置中,Spring能够帮助管理不同的数据源,通过配置bean来切换和控制数据源的使用。 **SpringMVC** 是Spring框架的一部分,专为Web开发设计。它简化了模型-视图-控制器(Model-View-Controller,MVC)的...

    spring boot mybatis多数据源最简解决方案

    当我们的项目涉及到多数据源时,即需要连接并操作多个数据库,Spring Boot和MyBatis的整合就显得尤为重要。本文将深入探讨如何实现Spring Boot结合MyBatis的多数据源最简解决方案。 首先,我们来理解多数据源的需求...

    SpringBoot+gradle+mybatis多数据源动态配置

    综上所述,这个项目通过SpringBoot、Gradle和MyBatis,实现了一个支持多数据源动态切换的应用。开发者可以利用AOP在运行时根据业务逻辑选择合适的数据源,提高了系统的灵活性和可扩展性。同时,Gradle的使用使得依赖...

    Springboot mybatis多数据源配置项目实例

    Spring Boot 和 MyBatis 的组合提供了这样的灵活性,可以方便地进行多数据源配置。本项目实例将详细讲解如何在 Spring Boot 中集成 MyBatis 并配置多数据源。 首先,我们需要了解 Spring Boot 中的数据源配置。...

    mybatis+spring实现动态切换数据源

    通过以上步骤,我们就实现了MyBatis与Spring配合下的动态数据源切换。这种机制有助于在多租户系统、读写分离或者高可用架构中灵活地管理数据库访问,提高了系统的可扩展性和灵活性。在实际应用中,还需要考虑数据源...

    Spring+MyBatis多数据源配置实现

    总之,Spring+MyBatis多数据源配置是大型项目中常见的需求,它通过`AbstractRoutingDataSource`实现了动态数据源选择,结合MyBatis的Mapper接口和注解,可以方便地在多个数据库之间切换,从而满足复杂的数据库访问...

    springboot整合mybatis多数据源

    在Spring Boot应用中整合MyBatis并实现多数据源,是一项常见的需求,特别是在处理跨越不同数据库的数据时。Spring Boot以其便捷的自动配置特性,让这一过程变得相对简单,但同时也可能带来一些挑战。本文将深入探讨...

    SpringBoot-Mybatis多数据源.

    SpringBoot结合Mybatis实现多数据源的支持,可以有效地解决这些问题,提高系统的可扩展性和灵活性。本文将深入探讨如何在SpringBoot项目中配置和使用Mybatis的多数据源。 首先,我们要理解什么是多数据源。多数据源...

    使用springboot + JPA / MyBatis 实现多数据源动态切换

    4. **动态数据源切换**:对于MyBatis,可以在SqlSessionTemplate中设置数据源,或者使用`@MapperScan`注解配合自定义数据源路由类来实现。 **六、实战项目分析** 在`springboot-multi-datasource-master`项目中,...

    Mybatis+Spring+SpringMVC+quartz多数据源切换

    这个项目结合了四个关键的技术组件,它们分别是Mybatis、Spring、SpringMVC和Quartz,下面将详细介绍这些技术以及它们在多数据源切换和跨数据库同步中的应用。 **Mybatis** 是一款轻量级的Java持久层框架,它允许...

    Mybatis多数据源调用

    四、业务代码中的数据源切换 在业务代码中,可以通过ThreadLocal来保存当前线程所使用的数据源信息,然后在执行SQL时,动态数据源会根据这个信息选择正确的目标数据源。 ```java public class ...

    Springboot整合Druid与Mybatis的多数据源切换

    本教程将详细介绍如何在Spring Boot项目中整合Druid数据源池与Mybatis,实现多数据源切换的功能,并提供一个亲测可用的解决方案。 首先,让我们了解Spring Boot、Druid和Mybatis这三大组件的基础知识: **Spring ...

    SpringBoot整合mybatis-plus实现多数据源的动态切换且支持分页查询.pdf

    在SpringBoot项目中,整合Mybatis-Plus并实现多数据源的动态切换,同时支持分页查询是一项常见的需求。以下将详细阐述这个过程中的关键步骤和技术要点。 首先,我们需要引入必要的Maven依赖。这里提到了四个关键...

    mybatis+druid association 切换数据源

    本话题聚焦于"Mybatis+Druid Association 数据源切换",主要探讨在特定场景下如何解决Druid的DruidPooledStatement无法直接切换数据源的问题。 Druid是阿里巴巴开源的一个强大而全面的Java数据库连接池,它提供了...

Global site tag (gtag.js) - Google Analytics