SpringBoot项目数据库配置文件中配置多个数据源:

#********* primary jdbc **************************
spring.datasource.druid.primary.url=jdbc:mysql://127.0.0.1:3306/one?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&useSSL=false
spring.datasource.druid.primary.username=test1
spring.datasource.druid.primary.password=test1
spring.datasource.druid.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.primary.test-on-borrow=true
spring.datasource.druid.primary.test-while-idle=true
#********* primary jdbc ************************** #********* two jdbc **************************
spring.datasource.druid.two.url=jdbc:mysql://127.0.0.2:3306/two?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&useSSL=false
spring.datasource.druid.two.username=test2
spring.datasource.druid.two.password=test2
spring.datasource.druid.two.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.two.test-on-borrow=true
spring.datasource.druid.two.test-while-idle=true
#********* two jdbc **************************

数据源one(即主数据源)配置:

package com.test.common.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; /**
* <p>Description: primary数据库配置类 </p>*/
@Configuration
@MapperScan(basePackages = {"com.test.one.dao"}, sqlSessionTemplateRef = "sqlSessionTemplate")
public class DataSourceConfig { @Bean(name = "dataSource")public DataSource Datasource() {
return DruidDataSourceBuilder.create().build();
} /**
* 返回primary数据库的会话工厂
* @param ds
* @return
* @throws Exception
*/
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory SqlSessionFactory(@Qualifier("dataSource") DataSource ds) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(ds);
return bean.getObject();
} @Bean(name = "transactionManager")
public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
} /**
* 返回primary数据库的会话模板
* @param sessionFactory
* @return
* @throws Exception
*/
@Bean(name = "sqlSessionTemplate")
public SqlSessionTemplate SqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sessionFactory) throws Exception {
return new SqlSessionTemplate(sessionFactory);
}
}
@MapperScan(basePackages = {"com.test.one.dao"}, sqlSessionTemplateRef  = "sqlSessionTemplate")项目启动扫描
com.test.one.dao路径下的dao使用主数据源

package com.test.common.config;

import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.*; import java.util.Collections;
import java.util.HashMap;
import java.util.Map; /**
* <p>Description: primary事务配置 </p>*/
@Configurationpublic class TransactionConfig { /*
* 通过AOP切面设置全局事务,拦截service包下面所有方法
* AOP术语:通知(Advice)、连接点(Joinpoint)、切入点(Pointcut)、切面(Aspect)、目标(Target)、代理(Proxy)、织入(Weaving)
*/ /**
* 事务超时时间
*/
private static final int TX_METHOD_TIMEOUT = 5; /**
* 定义切点变量:拦截指定包下所有类的所有方法,返回值类型任意的方法
*/
private static final String AOP_POINTCUT_EXPRESSION = "execution(* com.test.*.*.impl.*.*(..))"; /**
* <p>Description: springBoot事务配置</p>*/
@Bean(name="txAdvice")
public TransactionInterceptor txAdvice( @Qualifier("transactionManager") PlatformTransactionManager transactionManager){
/*事务管理规则,声明具备事务管理的方法名*/
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
/*只读事物、不做更新删除等
当前存在事务就用当前的事务,当前不存在事务就创建一个新的事务*/
RuleBasedTransactionAttribute readOnlyRule = new RuleBasedTransactionAttribute();
//设置当前事务是否为只读事务,true为只读*/
readOnlyRule.setReadOnly(true);
//transactiondefinition 定义事务的隔离级别;
// PROPAGATION_NOT_SUPPORTED事务传播级别5,以非事务运行,如果当前存在事务,则把当前事务挂起
readOnlyRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED); RuleBasedTransactionAttribute requireRule = new RuleBasedTransactionAttribute();
//抛出异常后执行切点回滚*/
requireRule.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
//PROPAGATION_REQUIRED:事务隔离性为1,若当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。 */
requireRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
//设置事务失效时间,如果超过5秒,则回滚事务
requireRule.setTimeout(TX_METHOD_TIMEOUT);
Map<String, TransactionAttribute> txMap = new HashMap<>(20); txMap.put("add*",requireRule);
txMap.put("save*", requireRule);
txMap.put("insert*",requireRule);
txMap.put("delete*",requireRule);
txMap.put("remove*",requireRule);
txMap.put("update*",requireRule);
txMap.put("modify*",requireRule); txMap.put("get*",readOnlyRule);
txMap.put("query*", readOnlyRule);
txMap.put("find*", readOnlyRule);
txMap.put("select*",readOnlyRule);
source.setNameMap(txMap);
TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, source);
return txAdvice;
} /**
* 利用AspectJExpressionPointcut设置切面=切点+通知(写成内部bean的方式)
*/
@Bean(name="txAdviceAdvisor")
public Advisor txAdviceAdvisor(@Qualifier("txAdvice") TransactionInterceptor txAdvice){
//切面(Aspect):切面就是通知和切入点的结合。通知和切入点共同定义了关于切面的全部内容——它的功能、在何时和何地完成其功能。
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); //声明和设置需要拦截的方法,用切点语言描写
pointcut.setExpression(AOP_POINTCUT_EXPRESSION); return new DefaultPointcutAdvisor(pointcut, txAdvice);
}
}

数据源two配置:

package com.test.common.config;

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; /**
* <p>Description: two数据库配置类 </p>*/
@Configuration
@ConditionalOnProperty(prefix = "spring.datasource.druid.two" ,name = "url", matchIfMissing = false)
@MapperScan(basePackages = {"com.test.two.dao"}, sqlSessionTemplateRef = "twoSqlSessionTemplate")
public class twoDataSourceConfig { @Bean(name = "twoDataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid.two")
public DataSource twoDatasource() {
return DruidDataSourceBuilder.create().build();
} /**
* 返回two数据库的会话工厂
* @param ds
* @return
* @throws Exception
*/
@Bean(name = "twoSqlSessionFactory")
public SqlSessionFactory twoSqlSessionFactory(@Qualifier("twoDataSource") DataSource ds) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(ds);
return bean.getObject();
} @Bean(name = "twoTransactionManager")
public DataSourceTransactionManager twoTransactionManager(@Qualifier("twoDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
} /**
* 返回two数据库的会话模板
* @param sessionFactory
* @return
* @throws Exception
*/
@Bean(name = "twoSqlSessionTemplate")
public SqlSessionTemplate twoSqlSessionTemplate(@Qualifier("twoSqlSessionFactory") SqlSessionFactory sessionFactory) throws Exception {
return new SqlSessionTemplate(sessionFactory);
}
}
@MapperScan(basePackages = {"com.test.two.dao"}, sqlSessionTemplateRef  = "twoSqlSessionTemplate")项目启动扫描
com.test.two.dao路径下的dao使用two数据源
package com.test.common.config;

import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.*; import java.util.Collections;
import java.util.HashMap;
import java.util.Map; /**
* <p>Description: two事务配置 </p>*/
@Configuration
@ConditionalOnProperty(name ="spring.datasource.druid.two.driver-class-name",havingValue="com.mysql.cj.jdbc.Driver")
public class TransactionTwoConfig { /*
* 通过AOP切面设置全局事务,拦截service包下面所有方法
* AOP术语:通知(Advice)、连接点(Joinpoint)、切入点(Pointcut)、切面(Aspect)、目标(Target)、代理(Proxy)、织入(Weaving)
*/ /**
* 事务超时时间
*/
private static final int TX_METHOD_TIMEOUT = 5; /**
* 定义切点变量:拦截指定包下所有类的所有方法,返回值类型任意的方法
*/
private static final String AOP_POINTCUT_EXPRESSION = "execution(* com.test.*.*.impl.*.*(..))"; /**
* <p>Description: springBoot事务配置</p>*/
@Bean(name="txAdvice-two")
public TransactionInterceptor txAdvice( @Qualifier("twoTransactionManager") PlatformTransactionManager transactionManager){
/*事务管理规则,声明具备事务管理的方法名*/
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
/*只读事物、不做更新删除等
当前存在事务就用当前的事务,当前不存在事务就创建一个新的事务*/
RuleBasedTransactionAttribute readOnlyRule = new RuleBasedTransactionAttribute();
//设置当前事务是否为只读事务,true为只读*/
readOnlyRule.setReadOnly(true);
//transactiondefinition 定义事务的隔离级别;
// PROPAGATION_NOT_SUPPORTED事务传播级别5,以非事务运行,如果当前存在事务,则把当前事务挂起
readOnlyRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED); RuleBasedTransactionAttribute requireRule = new RuleBasedTransactionAttribute();
//抛出异常后执行切点回滚*/
requireRule.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
//PROPAGATION_REQUIRED:事务隔离性为1,若当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。 */
requireRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
//设置事务失效时间,如果超过5秒,则回滚事务
requireRule.setTimeout(TX_METHOD_TIMEOUT);
Map<String, TransactionAttribute> txMap = new HashMap<>(20); txMap.put("add*",requireRule);
txMap.put("save*", requireRule);
txMap.put("insert*",requireRule);
txMap.put("delete*",requireRule);
txMap.put("remove*",requireRule);
txMap.put("update*",requireRule);
txMap.put("modify*",requireRule); txMap.put("get*",readOnlyRule);
txMap.put("query*", readOnlyRule);
txMap.put("find*", readOnlyRule);
txMap.put("select*",readOnlyRule);
source.setNameMap(txMap);
TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, source);
return txAdvice;
} /**
* 利用AspectJExpressionPointcut设置切面=切点+通知(写成内部bean的方式)
*/
@Bean(name="txAdviceAdvisor-two")
public Advisor txAdviceAdvisor(@Qualifier("txAdvice-two") TransactionInterceptor txAdvice){
//切面(Aspect):切面就是通知和切入点的结合。通知和切入点共同定义了关于切面的全部内容——它的功能、在何时和何地完成其功能。
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); //声明和设置需要拦截的方法,用切点语言描写
pointcut.setExpression(AOP_POINTCUT_EXPRESSION); return new DefaultPointcutAdvisor(pointcut, txAdvice);
}
}

SpringBoot多数据源详细配置与使用(包含数据源和事务配置)的更多相关文章

  1. 170629、springboot编程之Druid数据源和监控配置二

    上篇是一种配置方式,虽然我们创建了servlet.filter但是没有任务编码,看着是不是很不爽.ok,接下来说一下简介的配置方式,使用代码注册Servlet,也是我个人比较推荐的! 1.创建Drui ...

  2. 170628、springboot编程之Druid数据源和监控配置一

    Spring Boot默认的数据源是:org.apache.tomcat.jdbc.pool.DataSource,那么如何修改数据源呢?我已目前使用比较多的阿里数据源Druid为例,如果使用其他的数 ...

  3. spring boot配置druid数据源和监控配置

    直接上代码: 一.pom.xml中添加依赖 <dependency> <groupId>com.github.drtrang</groupId> <artif ...

  4. 基于注解实现SpringBoot多数据源配置

    1.功能介绍 在实际的开发中,同一个项目中使用多个数据源是很常见的场景.最近在学习的过程中使用注解的方式实现了一个Springboot项目多数据源的功能.具体实现方式如下. 2.在applicatio ...

  5. spring学习笔记(22)声明式事务配置,readOnly无效写无异常

    在上一节内容中.我们使用了编程式方法来配置事务,这种优点是我们对每一个方法的控制性非常强.比方我须要用到什么事务,在什么位置假设出现异常须要回滚等.能够进行非常细粒度的配置.但在实际开发中.我们可能并 ...

  6. DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描

    DB数据源之SpringBoot+MyBatis踏坑过程(三)手工+半自动注解配置数据源与加载Mapper.xml扫描 liuyuhang原创,未经允许禁止转载    系列目录连接 DB数据源之Spr ...

  7. Spring-Boot 多数据源配置+动态数据源切换+多数据源事物配置实现主从数据库存储分离

    一.基础介绍 多数据源字面意思,比如说二个数据库,甚至不同类型的数据库.在用SpringBoot开发项目时,随着业务量的扩大,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源. ...

  8. Springboot 多数据源配置,结合tk-mybatis

    一.前言 作为一个资深的CRUD工程师,我们在实际使用springboot开发项目的时候,难免会遇到同时使用多个数据库的情况,比如前脚刚查询mysql,后脚就要查询sqlserver. 这时,我们很直 ...

  9. springboot多数据源的配置与使用

    转自:https://www.jianshu.com/p/34730e595a8c 之前在介绍使用JdbcTemplate和Spring-data-jpa时,都使用了单数据源.在单数据源的情况下,Sp ...

  10. springboot区分开发、测试、生产多环境的应用配置(二)

    转:https://www.jb51.net/article/139119.htm springboot区分开发.测试.生产多环境的应用配置(二) 这篇文章主要给大家介绍了关于maven profil ...

随机推荐

  1. kafak学习总结

    高可用 多副本机制: 主副本和从副本,从副本只负责同步主副本数据,只有主副本进行读写. 高并发 网络结构设计 多路复用 多selector -> 多线程-> 多队列 高性能 写 把数据先写 ...

  2. iOS开发之权限申请说明key

    我们申请不同的权限需要对应的key,在info.plist内加上对用户的提示语 麦克风权限 NSMicrophoneUsageDescription 相机权限 NSCameraUsageDescrip ...

  3. WOW事件大全(翻译对照)

    魔兽世界(WOW)插件开发事件大全 ACHIEVEMENT_EARNED 取得的成就 ACHIEVEMENT_SEARCH_UPDATED 已更新成就搜索 ACTIONBAR_HIDEGRID 动作条 ...

  4. ASP.NET Core实现自定义中间件的三种方式

    一.什么是中间件 请求处理管道由一系列中间件组件组成.每个组件在 HttpContext 上执行操作,调用管道中的下一个中间件或终止请求. 详情请看另外一篇文章:白话管道中间件 下图是中间件的管道模型 ...

  5. CSMA/CA多路复用、载波监听、冲突避免

    CSMA/CA是避免各站点之间数据传输冲突的算法,其特点是发送包的同时不能检测到信道上有无冲突,只能尽量"避免".例如,如果计算机A和计算机C同时给计算机B发送一个控制消息,它们将 ...

  6. ChatGPT检测器开发者在知乎的文章,记录一下

    我们开发了第一款中英双语ChatGPT检测器,还有... - 蝈蝈的文章 - 知乎 https://zhuanlan.zhihu.com/p/598395917

  7. PR如何导出mp4格式的视频

    PR如何导出mp4格式的视频 PR是一款强大的视频处理软件,有时我们想导出mp4格式的视频,但好像找不到这种格式,具体怎么操作呢?PR如何导出mp4格式的视频? 1.打开PR,然后处理完视频后,点击左 ...

  8. URLDecoder.decode() 特殊字符的处理

    在网络get请求中,如果存在特殊字符 比如  "+,/,%,&,= " ,如果没有被转义就直接使用 发现 + 号 仍然是 + 号,初看上去是没什么问题  这样在我们在后台接 ...

  9. 通过Python获取cpu、硬盘和主板等硬件序列号组成的唯一识别码

    import wmi c = wmi.WMI() def yingpan(): # # 硬盘序列号 cc = "" for physical_disk in c.Win32_Dis ...

  10. vue 中的 provide/inject

    provide/inject 是 vue 2.2.0 版本新增 类型: provide:Object | () => Object inject:Array<string> | { ...