基于注解的Spring多数据源配置和使用(非事务)
本文内容纲要:基于注解的Spring多数据源配置和使用(非事务)
原文:基于注解的Spring多数据源配置和使用
1。创建DynamicDataSource类,继承AbstractRoutingDataSource
package com.rps.dataSource;import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder.getDataSource();
}
}
创建DynamicDataSourceHolder类
package com.rps.dataSource;public class DynamicDataSourceHolder {
/**
* 注意:数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰
*/
private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal<String>();
public static String getDataSource() {
return THREAD_DATA_SOURCE.get();
}
public static void setDataSource(String dataSource) {
THREAD_DATA_SOURCE.set(dataSource);
}
public static void clearDataSource() {
THREAD_DATA_SOURCE.remove();
}
}
2.配置多数据源
<util:properties id="jdbc" location="classpath:etc/mybatis/db.properties" />
<!-- 连接池配置开始 -->
<!-- Druid连接池 -->
<bean id="druidDataSourceAccount" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close" lazy-init="true">
<property name="driverClassName" value="#{jdbc.driverClassName}" />
<property name="url" value="#{jdbc.account_url}" />
<property name="username" value="#{jdbc.username}" />
<property name="password" value="#{jdbc.password}" />
</bean>
<bean id="druidDataSourceCommon" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close" lazy-init="true">
<property name="driverClassName" value="#{jdbc.driverClassName}" />
<property name="url" value="#{jdbc.common_url}" />
<property name="username" value="#{jdbc.username}" />
<property name="password" value="#{jdbc.password}" />
</bean>
<bean id="druidDataSourceData" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close" lazy-init="true">
<property name="driverClassName" value="#{jdbc.driverClassName}" />
<property name="url" value="#{jdbc.data_url}" />
<property name="username" value="#{jdbc.username}" />
<property name="password" value="#{jdbc.password}" />
</bean>
<!-- 连接池配置结束 -->
<!-- MyBatis整合开始 -->
<bean id="dynamicDataSource" class="com.rps.dataSource.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="account" value-ref="druidDataSourceAccount"></entry>
<entry key="common" value-ref="druidDataSourceCommon"></entry>
<entry key="data" value-ref="druidDataSourceData"></entry>
</map>
</property>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dynamicDataSource"/>
<property name="mapperLocations" value="classpath:com/rps/**/*.xml"/>
<property name="configLocation" value="classpath:etc/mybatis/mybatis-config.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.rps" />
<property name="annotationClass" value="com.rps.annotations.MyBatisRepository" />
</bean>
<!-- MyBatis整合结束 -->
<!-- 配置数据库事务开始 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dynamicDataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
<!-- 配置数据库事务结束 -->
3.在使用数据源前,选择数据源:
DynamicDataSourceHolder.setDataSource("account");
或:使用spring aop 动态切换:
package com.rps.aspect;import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import com.rps.annotations.DataSource;
import com.rps.dataSource.DynamicDataSourceHolder;
@Component
@Aspect
public class DataSourceAspect {
/**
* 拦截目标方法,获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源
*
* @param point
* @throws Exception
*/
@Before("execution(* com.rps.*.model.dao.*.*(..))")
public void intercept(JoinPoint point) throws Exception {
System.out.println("*****************************");
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((Class<? extends Annotation>) DataSource.class)) {
DataSource source = clazz.getAnnotation(DataSource.class);
DynamicDataSourceHolder.setDataSource(source.value());
}
// 方法注解可以覆盖类型注解
Method m = clazz.getMethod(method.getName(), types);
if (m != null && m.isAnnotationPresent(DataSource.class)) {
DataSource source = m.getAnnotation(DataSource.class);
DynamicDataSourceHolder.setDataSource(source.value());
}
} catch (Exception e) {
System.out.println(clazz + ":" + e.getMessage());
}
}
}
注:事务管理配置一定要配置在往DynamicDataSourceHolder 中注入数据源key之前 ,否则会报 Could not open JDBC Connection for transaction; nested exception is java.lang.IllegalStateException: Cannot determine target DataSource for lookup key [null] 找不到数据源错误
本文内容总结:基于注解的Spring多数据源配置和使用(非事务)
原文链接:https://www.cnblogs.com/qingyibusi/p/6590489.html
以上是 基于注解的Spring多数据源配置和使用(非事务) 的全部内容, 来源链接: utcz.com/z/296199.html