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

最近做流程遇到需求:

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

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

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

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

所以解决方案应该为: 

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

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

           sqlsessionFactory1---->datasource_engine

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

 

1:实现数据源切换

         DynamicDataSourceHolder.java

           

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

	private static final ThreadLocal local = new ThreadLocal();
	
	/**
	 * 清空当前数据源
	 */
	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配置

  


			
		
		
		 
			
		
		
		
			
				
					
					
				
			
			
		
		
		
			
		

 使用此种方式  切源数据源的话只需要设置代码: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

 改成

  配置文件如下:

   


			
			
			
		
		
		
			
			
			
		
		
		
			
				
					sqlserver
					db2
					oracle
				
			
		
		
		
			
		
		
		
		
			
			
			
		
		
		
			
			
			
		

 

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

      

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

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

 

public @interface EngineRepository {
}
public @interface BusinessRepository {
}

你可能感兴趣的:(mybatis)