基于注解的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

回到顶部