基于注解的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多数据源配置和使用(非事务)的更多相关文章
- 基于注解的Spring多数据源配置和使用
前一段时间研究了一下spring多数据源的配置和使用,为了后期从多个数据源拉取数据定时进行数据分析和报表统计做准备.由于之前做过的项目都是单数据源的,没有遇到这种场景,所以也一直没有去了解过如何配置多 ...
- 基于xml的Spring多数据源配置和使用
上一篇讲了<基于注解的Spring多数据源配置和使用>,通过在类或者方法上添加@DataSource注解就可以指定某个数据源.这种方式的优点是控制粒度细,也更灵活. 但是当有些时候项目分模 ...
- 基于注解的Spring AOP的配置和使用
摘要: 基于注解的Spring AOP的配置和使用 AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不 ...
- 基于注解实现SpringBoot多数据源配置
1.功能介绍 在实际的开发中,同一个项目中使用多个数据源是很常见的场景.最近在学习的过程中使用注解的方式实现了一个Springboot项目多数据源的功能.具体实现方式如下. 2.在applicatio ...
- 基于注解的Spring AOP的配置和使用--转载
AOP是OOP的延续,是Aspect Oriented Programming的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. ...
- spring基于通用Dao的多数据源配置详解【ds1】
spring基于通用Dao的多数据源配置详解 有时候在一个项目中会连接多个数据库,需要在spring中配置多个数据源,最近就遇到了这个问题,由于我的项目之前是基于通用Dao的,配置的时候问题不断,这种 ...
- Spring系列9:基于注解的Spring容器配置
写在前面 前面几篇中我们说过,Spring容器支持3种方式进行bean定义信息的配置,现在具体说明下: XML:bean的定义和依赖都在xml文件中配置,比较繁杂. Annotation-based ...
- Spring7:基于注解的Spring MVC(下篇)
Model 上一篇文章<Spring6:基于注解的Spring MVC(上篇)>,讲了Spring MVC环境搭建.@RequestMapping以及参数绑定,这是Spring MVC中最 ...
- 基于注解的Spring AOP入门、增强Advice实例
这篇文章简单通过一个例子,介绍几种增强的基本配置,以方便spring框架初学者对aop的代码结构有个清楚的了解认识.首先,spring支持aop编程,支持aspectJ的语法格式来表示切入点,切面,增 ...
随机推荐
- POJ1236:Network of Schools (思维+Tarjan缩点)
Network of Schools Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 24880 Accepted: 99 ...
- bzoj 1218 [HNOI2003]激光炸弹 二维前缀和
[HNOI2003]激光炸弹 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3022 Solved: 1382[Submit][Status][Di ...
- HUST 1103 校赛 邻接表-拓扑排序
Description N students were invited to attend a party, every student has some friends, only if someo ...
- 基本控件文档-UILabel属性---iOS-Apple苹果官方文档翻译
本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址 //转载请注明出处--本文永久链接:http://www.cnblogs.com/ ...
- 启动Eclipse时,弹出failed to load the jni shared library
JDK版本和Eclipse版本不同的问题,JDK版本为64位,Eclipse版本为32位.
- 2017-2018-1 《Linux内核原理与设计》第十二周作业
<linux内核原理与设计>第十二周作业 Sql注入基础原理介绍 分组: 和20179215袁琳完成实验 一.实验说明 SQL注入攻击通过构建特殊的输入作为参数传入Web应用程序,而这 ...
- Object的公用方法们
如图所示,Object一共有10种方法: 下面详细描述: 1.public Object() 方法,默认构造函数方法,当新建一个Object对象的时候,调用这个方法向堆区申请一片内存: 2.priva ...
- tornado简单使用
这篇适用于快速上手想了解更深:http://www.tornadoweb.cn/ https://tornado-zh.readthedocs.io/zh/latest/ Tornado 是 Fr ...
- centos7系统安装配置
下载centos7 iso镜像 电脑里面本来有ubuntu系统,直接在u盘做好启动盘安装即可,选择手动分区(忘了),将原本ubuntu系统分区压缩200G.系统不要选择最小化,选择gnome的图形界面 ...
- 如何得知 kernel 或 android 已開機多久時間
adb shell cat /proc/uptime 中的第一個數字, adb shell cat "/proc/uptime" 210.79 312.76 或者是 kernel ...