<强>需求:强>
有些时候,我们需要连接多个数据库,但是,在方法调用前并不知道到底是调用哪个。即同时保持多个数据库的连接,在方法中根据传入的参数来确定。
下图的单数据源的调用和多数据源动态调用的流程,可以看出在Dao层中需要有一个数据源选择器,来确定到底是调用哪个数据源。
<>强实现方式强>
对Dao层提供一个公共父类,保持有多个数据源的连接(本人是基于iBatis,即保持多个SQLSessionTemplate)
/* * *由hzlizhou> 公共接口MultiDataSourceSelector { 字符串getName (); } 公共类DubboContextDataSourceSelector实现MultiDataSourceSelector { 私人字符串defaultName; 公共DubboContextDataSourceSelector(字符串defaultName) { this.defaultName=defaultName; } @Override 公共字符串getName () {//DubboContextHolder是一个保持一个ThreadLocal的地图 字符串res=DubboContextHolder.getContext () . get (DubboContextConstants.CLUSTER_NAME); 如果(res==null) { res=getDefaultName (); } 返回res; } 公共字符串getDefaultName () { 返回defaultName; } } >之前然后在Dao层的中获取SQLSessionTemplate的时候就是动态了。
<强>动态事务强>
其实这个都好办,然后我们就面临一个稍微复杂一点的问题,那数据源是动态的,事务也就必须是动态了的,而且还对原有的代码没有侵入(例如春天中的@ transactional注解),那实现一个类似@ transactional的方法吧。名字就叫做@DynamicTransactional
@Documented @Target({方法,类型}) @Retention(运行时) 公共@ interface DynamicTransactional { 传播传播()缺省Propagation.REQUIRED; Class<& # 63;扩展Throwable> [] rollbackFor违约(){}; } >之前基本思想是在通过AOP切面拦截@DynamicTransactional注解,调用,然后自己编程实现事务
切面内的核心方法是
私有对象invokeWithinTransaction(最终ProceedingJoinPoint pjp、最终DynamicTransactional dynamicTransaction) {//创建TransactionTemplate 最后PlatformTransactionManager tran=multiTransactionManagerHolder.getTransactionManager (); TransactionTemplate TransactionTemplate=new TransactionTemplate (); transactionTemplate.setPropagationBehavior (dynamicTransaction.propagation () value ()); transactionTemplate.setTransactionManager (tran);//在事务中执行 transactionTemplate返回。执行(新的TransactionCallback