mybatis+spring双数据源配置

本文介绍了一种在MyBatis中实现多数据源动态切换的方法,包括配置文件、实现类及注解等关键部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mybatis.xml的配置:

	<!-- 动态数据源 -->
	<bean id="dataSource" class="org.gyy.dataSource.DynamicDataSource">
		<!-- 通过key-value关联数据源 -->
		<property name="targetDataSources">
			<map>
				<entry value-ref="dataSourceOne" key="dataSourceOne" />
				<entry value-ref="dataSourceTwo" key="dataSourceTwo" />
			</map>
		</property>
		<property name="defaultTargetDataSource" ref="dataSourceOne" />
	</bean>

	<!-- 配置数据源(一) -->
	<bean name="dataSourceOne" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
		<!-- 基本配置 -->
		<property name="driverClassName" value="${db1.driverClassName}" />
		<property name="url" value="${db1.url}" />
		<property name="username" value="${db1.user}" />
		<property name="password" value="${db1.password}" />
		<!-- 初始化时建立物理连接的个数 -->
		<property name="initialSize" value="${db1.initialSize}" />
		<!-- 最小连接池数 -->
		<property name="minIdle" value="${db1.minIdle}" />
		<!-- 最大连接池数量 -->
		<property name="maxActive" value="${db1.maxActive}" />
		<!-- 配置获取连接等待超时的时间 -->
		<property name="maxWait" value="${db1.maxWait}" />
		<!-- 数据源监控配置 
		<property name="filters" value="stat" /> -->
		<!-- 多数据源监控配置 -->
		<property name="useGlobalDataSourceStat" value="true" />
	</bean>

	<!-- 配置数据源(二) -->
	<bean name="dataSourceTwo" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
		<!-- 基本配置 -->
		<property name="driverClassName" value="${db2.driverClassName}" />
		<property name="url" value="${db2.url}" />
		<property name="username" value="${db2.user}" />
		<property name="password" value="${db2.password}" />
		<!-- 初始化时建立物理连接的个数 -->
		<property name="initialSize" value="${db2.initialSize}" />
		<!-- 最小连接池数 -->
		<property name="minIdle" value="${db2.minIdle}" />
		<!-- 最大连接池数量 -->
		<property name="maxActive" value="${db2.maxActive}" />
		<!-- 配置获取连接等待超时的时间 -->
		<property name="maxWait" value="${db2.maxWait}" />
		<!-- 数据源监控配置 
		<property name="filters" value="stat" /> -->
		<!-- 多数据源监控配置 -->
		<property name="useGlobalDataSourceStat" value="true" />
	</bean>
					
		<!-- 配置sqlSessionFactory(由mybatis-spring.jar提供支持) -->
	<bean name="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!-- 配置数据源 -->
		<property name="dataSource" ref="dataSource" />
		<!-- 配置mybatis的默认选项 -->
		<property name="configuration" ref="configuration" />
	</bean>
	<!-- mybatis默认选项配置 -->
	<bean id="configuration" class="org.apache.ibatis.session.Configuration">
		<property name="callSettersOnNulls" value="true" />
	</bean>

	<!-- Mapper接口所在包名,Spring会自动查找其下的Mapper -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="org.gyy.mapper..*" />
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
	</bean>
	<!-- 支持注解事务模式 -->
	<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

	<!-- 事务管理 -->
	<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>

	<!-- 配置声明式事务 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
			<tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
			<tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
			<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
		</tx:attributes>
	</tx:advice>
	<!-- 拦截数据源注解,注入数据源 -->
	<bean id="dataSourceAspect" class="org.gyy.dataSource.DataSourceAspect" />

	<!-- 配置该声明式事务规则用于的切入点 步骤: 1.配置切入点 2.应用该声明式事务规则 -->
	<aop:config proxy-target-class="true" expose-proxy="true">
		<!-- 配置切入点 -->
		<aop:pointcut id="transaction_pointcut" expression="execution(* org.gyy.service.impl..*.*(..))" />
		<!-- 应用该声明式事务规则 -->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="transaction_pointcut" order="2" />
		<aop:aspect ref="dataSourceAspect" order="1">
			<!-- 拦截所有service方法 -->
			<aop:pointcut id="dataSourcePointcut" expression="execution( * org.gyy.service.impl..*.*(..))" />
			<aop:before pointcut-ref="dataSourcePointcut" method="intercept" />
		</aop:aspect>
	</aop:config>
DynamicDataSource实现类:

package org.gyy.dataSource;

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

public class DynamicDataSource extends AbstractRoutingDataSource {  
  @Override    
  protected Object determineCurrentLookupKey() {       
	  return DataSourceContextHolder.getDataSourceType(); 
    }
}
DataSourceContextHolder类:

package org.gyy.dataSource;
public class DataSourceContextHolder {
	private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
	/**
	 * @Description: 设置数据源类型
	 * @param dataSourceType  数据库类型
	 * @return void
	 * @throws
	 */
	public static void setDataSourceType(String dataSourceType) {
		contextHolder.set(dataSourceType);
	}
	
	/**
	 * @Description: 获取数据源类型
	 * @param 
	 * @return String
	 * @throws
	 */
	public static String getDataSourceType() {
		return contextHolder.get();
	}
	
	/**
	 * @Description: 清除数据源类型
	 * @param 
	 * @return void
	 * @throws
	 */
	public static void clearDataSourceType() {
		contextHolder.remove();
	}
}
DataSourceAspect:拦截方法,动态拦截数据源标签实现动态切换:

package org.gyy.dataSource;

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DataSourceAspect {
	private static final Logger logger = LoggerFactory.getLogger(DataSourceAspect.class);

	/**
	 * 拦截目标方法,获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源
	 * 
	 * @param point
	 * @throws Exception
	 */
	public void intercept(JoinPoint point) throws Exception {
		Class<?> target = point.getTarget().getClass();
		MethodSignature signature = (MethodSignature) point.getSignature();
		/* 默认使用目标类型的注解,如果没有则使用其实现接口的注解 */
		for (Class<?> clazz : target.getInterfaces()) {
			resolveDataSource(clazz, signature.getMethod());
		}
		resolveDataSource(target, signature.getMethod());
	}


	/**
	 * 提取目标对象方法注解和类型注解中的数据源标识
	 * 
	 * @param clazz
	 * @param method
	 */
	private void resolveDataSource(Class<?> clazz, Method method) {
		try {
			Class<?>[] types = method.getParameterTypes();
			// 默认使用类型注解
			if (clazz.isAnnotationPresent(DataSource.class)) {
				DataSource source = clazz.getAnnotation(DataSource.class);
				DataSourceContextHolder.setDataSourceType(source.value());
			}
			// 方法注解可以覆盖类型注解
			Method m = clazz.getMethod(method.getName(), types);
			if (m != null && m.isAnnotationPresent(DataSource.class)) {
				DataSource source = m.getAnnotation(DataSource.class);
				DataSourceContextHolder.setDataSourceType(source.value());
			}
		} catch (Exception e) {
			e.printStackTrace();
			if (logger.isErrorEnabled()) {
				logger.error("DataSourceAspect Error :[{}]", e);
			}
		}
	}

}

自定义数据源标签:

package org.gyy.dataSource;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/** 
* @date 2017年7月14日 
* @version 1.0
* @description 多数据源注解
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface DataSource {
	/** 
	* @return {@link String}
	* @date 2017年7月15日 
	* @version 1.0
	* @description 数据源名称,来源Spring配置
	*/
	String value();
}

以上的代码就可以实现多数据源的切换了;

这是使用方式,标签里面的值就是自己注入时定义的key,spring也会根据这个去注入。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值