最近做流程遇到需求:
一个流程引擎的数据源,所有流程数据都在此数据源
针对多个系统多个 用户相关数据源
流程中只保存 用户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 { }
相关推荐
spring mybatis 多数据源动态切换
spring整合mybatis多数据源切换 可以运行的demo实例
SpringBoot+gradle+mybatis多数据源动态配置 AOP的方式实现数据源动态切换。
springboot+druid+mybatis多数据源动态切换,基于sql类型完成读写分离操作
mybatis+spring实现动态切换数据源,修改数据源配置信息之后,直接运行test可进行测试
使用springboot + JPA / MyBatis 实现多数据源动态切换
SpringBoot整合mybatis-plus实现多数据源的动态切换且支持分页查询,案例以postgresql和oracle数据库为数据源,分别使用mybatis-plus分页插件和pagehelper分页插件实现分页查询。
Mybatis+Spring+SpringMVC+quartz多数据源切换 定时任务 多数据库之间同步
Spring-boot+mybatis多数据源整合(动态切换数据源),亲测可用
读写库分离,动态数据源切换,mybitis动态数据源,SSM动态数据源,多数据源
踩坑实录 亲测可用的springboot 整合mybatis druid 多数据源切换方案 使用注解方式更加灵活
springmvc mybatis 多数据源,完整项目
SpringBootDemo_mutilDatasource是springboot基于mybatis多数据源实现的Demo
相信很多朋友在开发的时候,可能会碰到需要一个项目,配置多个数据源的需求,可能是同一种数据库,也可能是不同种类...多个数据源,动态切换 swagger-ui提供伪Restful接口文档 AOP实现统一入参校验 AOP实现统一异常处理
SpringMVC+Mybatis(多数据源)+Mongo(多数据源),框架适合同时访问多种DB,且支持每种DB配置多个数据源。正如我代码中的demo,配置了两个mysql数据源+2个mongo数据源,可以在service实现中随意访问。除此之外还通过...
Springboot+mybatis多数据源整合 抽象公告基础类 ,通过ThreadLocal实现数据源切换
mybatis-plus+动态数据源+自定义数据源配置+dom解析+自定义参数注入(注解)+AOP切换数据源+druid
springboot+mybatis+mysql+AbstractRoutingDataSource实现多数据源切换(一写多读数据源)项目中包含完整的demo案例配备文档说明,亲测可用;实现简单,代码思路清晰.
springboot实现数据源动态切换 注意事项: 1. 该demo采用yml配置数据库信息,注意url标签为jdbc-url 2.项目中加了日志输出,可看到完整执行过程 3.在Service中应用事务时,自定义的注解将失效,解决办法:可将注解...
springmvc+mybatis结合,多数据源配置,并实现注解aop动态切换,可实现数据库读写分离,maven结构。