Spring Boot 集成 Mybatis 实现双数据源

转载自   Spring Boot 集成 Mybatis 实现双数据源

这里用到了Spring Boot + Mybatis + DynamicDataSource配置动态双数据源,可以动态切换数据源实现数据库的读写分离。

添加依赖

加入Mybatis启动器,这里添加了Druid连接池、Oracle数据库驱动为例。

<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId>
</dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId>
</dependency><dependency><groupId>com.oracle</groupId><artifactId>ojdbc6</artifactId>
</dependency>

添加启动类

@EnableMybatis
@EnableTransactionManagement
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class Application {public static void main(String[] args) {SpringApplication.run(ServiceApplication.class, args);}}
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }):这里用到了双数据源,需要排除数据源的自动配置,如果只有一个数据源用Spring Boot的自动配置就行。

@EnableTransactionManagement:开启事务支持。

@EnableMybatis:开启Mybatis功能

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(MybatisConfig.class)
public @interface EnableMybatis {}

Mybatis配置类

@Configuration
@MapperScan(basePackages = DSConfig.BASE_PACKAGES)
public class MybatisConfig implements DSConfig {@Primary@Beanpublic DynamicDataSource dynamicDataSource(@Qualifier(DB_MASTER) DataSource master,@Qualifier(DB_SLAVE) DataSource slave) {Map<Object, Object> dsMap = new HashMap<>();dsMap.put(DB_MASTER, master);dsMap.put(DB_MASTER, slave);DynamicDataSource dynamicDataSource = new DynamicDataSource();dynamicDataSource.setDefaultTargetDataSource(master);dynamicDataSource.setTargetDataSources(dsMap);return dynamicDataSource;}@Beanpublic PlatformTransactionManager transactionManager(DynamicDataSource dynamicDataSource) {return new DataSourceTransactionManager(dynamicDataSource);}@Beanpublic SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource)throws Exception {SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(dynamicDataSource);sessionFactory.setMapperLocations(((ResourcePatternResolver) new PathMatchingResourcePatternResolver()).getResources(DSConfig.MAPPER_LOCATIONS));return sessionFactory.getObject();}}

DSConfig常量类:

public interface DSConfig {String DS_PREFIX = "spring.datasource";String DS_ACTIVE = "active";String DB_MASTER = "db-master";String DB_SLAVE = "db-slave";String DRUID = "druid";String DRUID_MONITOR_USERNAME = "spring.druid.username";String DRUID_MONITOR_PASSWORD = "spring.druid.password";String DRUID_MONITOR_URL = "/druid/*";String DRUID_FILTER_EXCLUSIONS = "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*";String DRUID_FILTER_URL = "/*";String BASE_PACKAGES = "com.example.**.mapper";String MAPPER_LOCATIONS = "mapper/**/*.xml";}

连接池配置类

Druid连接池的自动配置类:

@Configuration
@Import({ PropertiesConfig.class })
@ConditionalOnClass(DruidDataSource.class)
@ConditionalOnProperty(prefix = DSConfig.DS_PREFIX, value = DSConfig.DS_ACTIVE, havingValue = DSConfig.DRUID)
public class DruidAutoConfig implements DSConfig {private Logger logger = LoggerUtils.getLogger(this);@Bean(name = DB_MASTER, initMethod = "init", destroyMethod = "close")public DataSource dataSourceMaster(DruidMasterProperties masterProperties) throws SQLException {logger.debug("master properties: {}", masterProperties.toString());DruidDataSource dds = new DruidDataSource();dds.setDriverClassName(masterProperties.getDriverClassName());dds.setUrl(masterProperties.getUrl());dds.setUsername(masterProperties.getUsername());dds.setPassword(masterProperties.getPassword());dds.setInitialSize(masterProperties.getInitialSize());dds.setMinIdle(masterProperties.getMinIdle());dds.setMaxActive(masterProperties.getMaxActive());dds.setMaxWait(masterProperties.getMaxWait());dds.setTimeBetweenEvictionRunsMillis(masterProperties.getTimeBetweenEvictionRunsMillis());dds.setMinEvictableIdleTimeMillis(masterProperties.getMinEvictableIdleTimeMillis());dds.setValidationQuery(masterProperties.getValidationQuery());dds.setTestOnBorrow(masterProperties.isTestOnBorrow());dds.setTestWhileIdle(masterProperties.isTestWhileIdle());dds.setTestOnReturn(masterProperties.isTestOnReturn());dds.setPoolPreparedStatements(masterProperties.isPoolPreparedStatements());dds.setMaxPoolPreparedStatementPerConnectionSize(masterProperties.getMaxPoolPreparedStatementPerConnectionSize());dds.setFilters(masterProperties.getFilters());return dds;}@Bean(name = DB_SLAVE, initMethod = "init", destroyMethod = "close")public DataSource dataSourceSlave(DruidSlaveProperties slaveProperties) throws SQLException {logger.debug("slave properties: {}", slaveProperties.toString());DruidDataSource dds = new DruidDataSource();dds.setDriverClassName(slaveProperties.getDriverClassName());dds.setUrl(slaveProperties.getUrl());dds.setUsername(slaveProperties.getUsername());dds.setPassword(slaveProperties.getPassword());dds.setInitialSize(slaveProperties.getInitialSize());dds.setMinIdle(slaveProperties.getMinIdle());dds.setMaxActive(slaveProperties.getMaxActive());dds.setMaxWait(slaveProperties.getMaxWait());dds.setTimeBetweenEvictionRunsMillis(slaveProperties.getTimeBetweenEvictionRunsMillis());dds.setMinEvictableIdleTimeMillis(slaveProperties.getMinEvictableIdleTimeMillis());dds.setValidationQuery(slaveProperties.getValidationQuery());dds.setTestOnBorrow(slaveProperties.isTestOnBorrow());dds.setTestWhileIdle(slaveProperties.isTestWhileIdle());dds.setTestOnReturn(slaveProperties.isTestOnReturn());dds.setPoolPreparedStatements(slaveProperties.isPoolPreparedStatements());dds.setMaxPoolPreparedStatementPerConnectionSize(slaveProperties.getMaxPoolPreparedStatementPerConnectionSize());dds.setFilters(slaveProperties.getFilters());return dds;}@Beanpublic ServletRegistrationBean druidServletRegistrationBean(EnvConfig env) {String username = env.getStringValue(DSConfig.DRUID_MONITOR_USERNAME);String password = env.getStringValue(DSConfig.DRUID_MONITOR_PASSWORD);return new ServletRegistrationBean(new DruidStatViewServlet(username, password),DSConfig.DRUID_MONITOR_URL);}@Beanpublic FilterRegistrationBean druidFilterRegistrationBean() {WebStatFilter wsf = new WebStatFilter();FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();filterRegistrationBean.setFilter(wsf);filterRegistrationBean.setUrlPatterns(Arrays.asList(DSConfig.DRUID_FILTER_URL));filterRegistrationBean.setInitParameters(Collections.singletonMap("exclusions", DSConfig.DRUID_FILTER_EXCLUSIONS));return filterRegistrationBean;}}

根据类路径下有DruidDataSource这个类即有Druid这个jar包和配置文件中spring.datasource.active=druid才开启对Druid连接池的自动配置。

导入的配置文件:

@Configuration
@ComponentScan(basePackages = "com.example.common.config.properties")
public class PropertiesConfig {}

DruidMasterProperties、DruidSlaveProperties属性文件读取的配置省略。

连接池监控配置类:

public class DruidStatViewServlet extends StatViewServlet {private static final long serialVersionUID = 1L;private String username;private String password;@Overridepublic String getInitParameter(String name) {if ("loginUsername".equals(name)) {return username;}if ("loginPassword".equals(name)) {return password;}return super.getInitParameter(name);}public DruidStatViewServlet(String username, String password) {super();this.username = username;this.password = password;}public String getUsername() {return username;}public String getPassword() {return password;}}

在META-INF/spring.factories中加入Druid自动配置映射:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.common.config.ds.DruidAutoConfig


切换数据源

切换数据源注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DS {String value() default DSConfig.DB_MASTER;
}

动态数据源类:

public class DynamicDataSource extends AbstractRoutingDataSource {private final Logger logger = LoggerUtils.getLogger(this);@Overrideprotected Object determineCurrentLookupKey() {logger.debug("当前数据源为{}", DataSourceContextHolder.getDS());return DataSourceContextHolder.getDS();}}

动态数据源AOP实现类:

@Aspect
@Component
public class DynamicDataSourceAspect {@Before("@annotation(DS)")public void beforeSwitchDS(JoinPoint point) {Class<?> className = point.getTarget().getClass();String methodName = point.getSignature().getName();Class<?>[] argClass = ((MethodSignature) point.getSignature()).getParameterTypes();String dataSource = DataSourceContextHolder.DEFAULT_DS;try {Method method = className.getMethod(methodName, argClass);if (method.isAnnotationPresent(DS.class)) {DS annotation = method.getAnnotation(DS.class);dataSource = annotation.value();}} catch (Exception e) {e.printStackTrace();}DataSourceContextHolder.setDS(dataSource);}@After("@annotation(DS)")public void afterSwitchDS(JoinPoint point) {DataSourceContextHolder.clearDS();}}

绑定当前线程数据源类:

public class DataSourceContextHolder {public static final String DEFAULT_DS = DSConfig.DB_MASTER;private static final ThreadLocal<String> DS_HOLDER = new ThreadLocal<>();public static void setDS(String dbType) {DS_HOLDER.set(dbType);}public static String getDS() {return (DS_HOLDER.get());}public static void clearDS() {DS_HOLDER.remove();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/328282.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.Net Core及.Net Standard主要概念回顾

在.Net Core之前&#xff0c;选择编译目标是一个相对简单的操作。现在&#xff0c;开发人员面临多种可能&#xff0c;选择一个目标不再那么显而易见了。要想对.Net Core有一个全面的了解&#xff0c;就要了解两个主要的概念&#xff1a;“目标框架别名&#xff08;Target Frame…

如何在Intellij IDEA中集成Gitlab

如何在Intellij IDEA中集成Gitlab 2018年06月11日 16:05:14 葬月魔帝 阅读数&#xff1a;9747 据说在微软收购github当天&#xff0c;一大批用户纷纷转向了gitlab和bitbucket&#xff0c;这两者也都是比较不错的代码托管网站&#xff0c;针对个人和企业都有对应的免费和收费版…

linux更改桌面壁纸的脚本,自动更换桌面壁纸的脚本,支持Ubuntu 18.04系统

下面提供一个自动更换桌面壁纸的脚本&#xff0c;它支持Ubuntu 18.04、UbuntuKylin 18.04、Ubuntu Mate系统。注意事项&#xff1a;1.默认的壁纸通常在目录路径为/usr/share/backgrounds中&#xff0c;如果不是请自行修改&#xff0c;不影响脚本的使用效果&#xff0c;注意目录…

推荐一个实用的 .gitignore 文件

转载自 推荐一个实用的 .gitignore 文件为什么要忽略文件&#xff1f; 常用的版本控制工具&#xff0c;不管是使用 git 还是 svn&#xff0c;我们都需要排除一些与程序代码无关的文件&#xff0c;如像 eclipse/ intellij idea 等 IDE 工具留下来的 .settings、 .classpath、…

应用工具 .NET Portability Analyzer 分析迁移dotnet core

大多数开发人员更喜欢一次性编写好业务逻辑代码&#xff0c;以后再重用这些代码。与构建不同的应用以面向多个平台相比&#xff0c;这种方法更加容易。如果您创建与 .NET Core 兼容的.NET 标准库&#xff0c;那么现在比以往任何时候都更接近于这一现实。 但是&#xff0c;现有的…

idea安装插件plugin(主要针对网络连接不上的情况)

idea安装插件plugin(主要针对网络连接不上的情况) 2018年04月27日 11:07:36 多机智 阅读数&#xff1a;10097 STEP1: ctrl alt s 打开settings STEP2: 在输入框键入 Plugins STEP3: 输入你想要的插件名称&#xff0c;我这边输入的是nodejs,因为最近在学(我这边是安装过…

linux打开服务iis,如何在Linux中引导时列出启动服务?

根据不同的启动系统&#xff0c;查找启动服务的列表会有所不同。Systemd是主要新版本Linux发行版的默认启动系统。如果您的系统使用systemd系统管理器&#xff0c;您可以使用以下命令列出所有服务。$ sudo systemctl list-unit-files --typeservice如上所述&#xff0c;这个命令…

银行营业网点管理系统——Servlet包(CityAreaServlet )

package BranchesMgr.servlet; /*** 城区表的Servlet*/ import java.io.IOException; import java.io.PrintWriter; import java.util.List;import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; im…

.NET Core中使用Razor模板引擎

一、简介 在MVC以外的场景中&#xff0c;我们往往需要完成一些模板引擎生成代码或页面的工作&#xff1b;在以前我们一般常用的有Razor、NVeocity、VTemplate。虽然所有的模板系统都具有一些共同特征&#xff0c;但 Razor却和我们前面讨论的二种视图引擎截然不同。不同于其它视…

idea中Gitlab项目导入导出

idea中Gitlab项目导入导出 2018年04月16日 16:39:23 蓝之刃 阅读数&#xff1a;15415 Gitlab的使用 Gitlab跟Github类似&#xff0c;都是代码托管的网站&#xff0c;最大的不同是Gitlab创建的项目可以免费私有的&#xff0c;不必像Github那样收费&#xff0c;而且Gitlab还可…

服务器 ha linux,Linux 高可用(HA)集群之Heartbeat详解

大纲一、Heartbeat 的定义二、Heartbeat 的版本与组件三、Heartbeat 的各版本之间的区别四、Heartbeat 集群的一般拓扑图推荐阅读&#xff1a;一、Heartbeat的定义Heartbeat 项目是 Linux-HA 工程的一个组成部分&#xff0c;也是目前开源HA项目中最成功的一个例子&#xff0c;L…

一篇文章彻底了解清楚什么是负载均衡

转载自 一篇文章彻底了解清楚什么是负载均衡 负载均衡是高可用网络基础架构的的一个关键组成部分&#xff0c;有了负载均衡&#xff0c;我们通常可以将我们的应用服务器部署多台&#xff0c;然后通过负载均衡将用户的请求分发到不同的服务器用来提高网站、应用、数据库或其他…

intellij-IDE运行Java程序报错:java: -source 1.5 中不支持 lambda 表达式 有用

intellij-IDE运行Java程序报错&#xff1a;java: -source 1.5 中不支持 lambda 表达式 2017年12月29日 15:04:15 佛空如水 阅读数&#xff1a;795 报错&#xff1a; 解决&#xff1a; 第一步修改&#xff1a; 第二步修改&#xff1a;

linux驱动开发音频设备驱动,linux驱动开发—基于Device tree机制的驱动编写

摘要&#xff1a;媒介 Device Tree是一种用去描绘硬件的数据布局&#xff0c;类似板级描绘说话&#xff0c;发源于OpenFirmware(OF)。正在现在遍及应用的kernel 2.6.x版本中&#xff0c;对分歧仄台、分歧硬件&#xff0c;往]前言Device Tree是一种用来描述硬件的数据结构&#…

gRPC .NET Core跨平台学习

前些天发布gRPC C# 学习&#xff0c;在.NET Framework 中使用gRPC &#xff0c;今天来学习 .NET Core gRPC。 gRPC 的.NET Core 包在NuGet 上发布了&#xff0c;结合.NET Core 实现gRPC 完美跨平台。 本篇主要讲解 .NET Core 版gRPC客户端运行在Ubuntu系统上&#xff0c;与局域…

IDEA导入Maven项目,pom.xml文件中 有inspects a maven model for resolution problems报错 !!!!!!!!!!有用

IDEA导入Maven项目&#xff0c;pom.xml文件中 有inspects a maven model for resolution problems报错 2018年08月06日 22:13:09 东方不能败 阅读数&#xff1a;4616 我是导入一个已经写好的Maven工程&#xff0c;导入后返现在pom.xml文件中有inspects a maven model for res…

Windows Server 2016提供Docker原生运行的企业级支持

Windows Server 2016已原生支持Docker&#xff0c;这使得Windows应用可运行在容器中。该评估版目前已经可用&#xff0c;期望于本月底之前&#xff0c;Microsoft将提供从评估版到RTM的升级路径。该评估版发布于上周的Microsoft Ignite大会上&#xff0c;同时还发布了Microsoft和…

arm linux串口控制led,通信程序设计 - Linux下ARM和单片机的串口通信设计

3 通信程序设计ARM 与单片机的串口通信程序包括两方面&#xff1a; 一方面是作为上位机的ARM 的串口通信程序&#xff0c;另一方面是作为下位机的单片机的串口通信程序。在通信之前必须制定合理的通信协议以保证通信的可靠性和成功率。现约定双方通信协议如下&#xff1a;( 1) …

为什么我强烈建议大家使用枚举来实现单例

转载自 为什么我墙裂建议大家使用枚举来实现单例 关于单例模式&#xff0c;我的博客中有很多文章介绍过。作为23种设计模式中最为常用的设计模式&#xff0c;单例模式并没有想象的那么简单。因为在设计单例的时候要考虑很多问题&#xff0c;比如线程安全问题、序列化对单例的…

idea @Data 不起作用找不到 相关的注解

idea中Data标签getset不起作用(这个有用&#xff0c;下面的没用) 2017年06月08日 11:22:40 seapeak007 阅读数&#xff1a;25816 spring cloud中使用Data标签&#xff0c;不用手动添加get set方法&#xff0c;但是如果项目中其他类中使用getset方法&#xff0c;如果报错&…