SpringBoot2 + Druid + Mybatis 多数据源配置

在大数据高并发的应用场景下,为了更快的响应用户请求,读写分离是比较常见的应对方案。读写分离会使用多数据源的使用。下面记录如何搭建SpringBoot2 + Druid + Mybatis  多数据源配置以及在使用过程遇到的问题。

一、先从pom.xml入手(使用springboot 2的版本)

<parent>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-parent</artifactId>    <version>2.1.5.RELEASE</version></parent>
<dependencies>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter</artifactId>    </dependency>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-web</artifactId>    </dependency>    <dependency>        <groupId>org.mybatis.spring.boot</groupId>        <artifactId>mybatis-spring-boot-starter</artifactId>        <version>2.0.1</version>    </dependency>    <dependency>        <groupId>mysql</groupId>        <artifactId>mysql-connector-java</artifactId>        <version>8.0.16</version>    </dependency>    <dependency>        <groupId>com.alibaba</groupId>        <artifactId>druid-spring-boot-starter</artifactId>        <version>1.1.17</version>    </dependency>    <dependency>        <groupId>javax.inject</groupId>        <artifactId>javax.inject</artifactId>        <version>1</version>    </dependency></dependencies>

inject是java依赖注入标准。spring默认支持识别。spring自带的@Autowired的缺省情况等价于JSR-330的@Inject注解;@Qualifier的缺省的根据Bean名字注入情况等价于JSR-330的@Named注解。

二、添加读取DB的Mapper

@Mapperpublic interface AssetMapper {

    @Select("select * from Asset where account = #{account}")    Asset queryName(String account);}

此处使用mybatis的注解功能,因此可以少省去*.xml等配置文件。

三、添加多数据源的配置参数

spring.datasource.druid.write.url=jdbc:mysql://192.168.0.110:3306/master?characterEncoding=utf-8&serverTimezone=Asia/Shanghaispring.datasource.druid.write.username=rootspring.datasource.druid.write.password=123456spring.datasource.druid.write.driver-class-name=com.mysql.cj.jdbc.Driver#spring.datasource.druid.read.url=jdbc:mysql://192.168.0.110:3306/slave1?characterEncoding=utf-8&serverTimezone=Asia/Shanghaispring.datasource.druid.read.username=rootspring.datasource.druid.read.password=123456spring.datasource.druid.read.driver-class-name=com.mysql.cj.jdbc.Driver

新版本mysql的url后面必需要添加serverTimezone=。 不然会报以下异常:2019-06-05 18:47:24.058 ERROR 17804 --- [-Create-6910184] com.alibaba.druid.pool.DruidDataSource   : create connection SQLException, url: jdbc:mysql://localhost:3306/master, errorCode 0, state 01S00

java.sql.SQLException: The server time zone value ‘?й???????‘ is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.    

四、配置数据源

@Configurationpublic class DataSourceConfig {

    @Bean(name = "masterDataSource")    @ConfigurationProperties(prefix = "spring.datasource.druid.write")    @Primary    public DataSource masterDataSource() {        return DruidDataSourceBuilder.create().build();    }

    @Bean(name = "slaveDataSource")    @ConfigurationProperties(prefix = "spring.datasource.druid.read")    public DataSource slaveDataSource() {        return DruidDataSourceBuilder.create().build();    }

    @Inject    @Named("masterDataSource")    private DataSource masterDataSource;

    @Inject    @Named("slaveDataSource")    private DataSource slaveDataSource;

    /**     * 根据数据源创建SqlSessionFactory     */    @Bean    public SqlSessionFactory sqlSessionFactory(DynamicDataSource dataSource) throws Exception {        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();        sessionFactory.setDataSource(dataSource);        return sessionFactory.getObject();    }}

SqlSessionFactory必需要重新创建,若不创建会报循环调用异常

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ‘masterDataSource‘: Requested bean is currently in creation: Is there an unresolvable circular reference?

因为SqlSessionFactory还是走默认创建的方式 。

上下文中如何得知使用那个数据源,可使用ThreadLocal来处理。

五、数据源路由

public class DataSourceContextRouting implements AutoCloseable {

    static final ThreadLocal<String> dataSourceKeyThreadLocal = new ThreadLocal<>();

    public String getDataSourceName(){        String key = dataSourceKeyThreadLocal.get();        return StringUtils.isBlank(key) ?"masterDataSource":key;    }

    public DataSourceContextRouting(String key){        dataSourceKeyThreadLocal.set(key);    }

    @Override    public void close() throws Exception {        dataSourceKeyThreadLocal.remove();    }}

spring的提供动态源实现功能。只需要继承AbstractRoutingDataSource,并重写protected Object determineCurrentLookupKey()

public class DynamicDataSource extends AbstractRoutingDataSource {    @Override    protected Object determineCurrentLookupKey() {        return  DataSourceContextRouting.getDataSourceName();    }}

//此为核心代码

@Bean

public DynamicDataSource dataSource() {    Map<Object, Object> targetDataSources = new HashMap<>();    targetDataSources.put("masterDataSource", masterDataSource);    targetDataSources.put("slaveDataSource", slaveDataSource);

    DynamicDataSource dataSource = new DynamicDataSource();    //设置数据源映射    dataSource.setTargetDataSources(targetDataSources);    //设置默认数据源,当无法映射到数据源时会使用默认数据源    dataSource.setDefaultTargetDataSource(slaveDataSource);    dataSource.afterPropertiesSet();    return dataSource;}

六、controller路由切换

 @RequestMapping("master")    public String master(String account){        String key = "masterDataSource";        new DataSourceContextRouting(key);        //TODO .....    }    @RequestMapping("slave")    public String slave(String account){        String key = "slaveDataSource";        new DataSourceContextRouting(key);      //TODO......    }

到此为止,整个多数据源配置完成了。

但这种对代码侵入比较多,可以使用注解的方式来处理。先定义注解标识

@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface TargetDataSource {    String value();    }

使用注解那需要对此进行解析切入,因此就需要用上spring AOP的功能。

首先添加maven依赖

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-aop</artifactId></dependency>

然后添加对其解析Aspect

@Aspect@Namedpublic class DataSourceRoutingAspect {    @Around("@annotation(targetDataSource)")    public Object routingWithDataSource(ProceedingJoinPoint joinPoint, TargetDataSource targetDataSource) throws Throwable {        String key = targetDataSource.value();        try (DataSourceContextRouting ctx = new DataSourceContextRouting(key)) {            return joinPoint.proceed();        }    }}

@RequestMapping("master")
@TargetDataSource("masterDataSource")
public String master(String account){
TODO:.....
}
@RequestMapping("slave")
@TargetDataSource("slaveDataSource")
public String slave(String account){
TODO:.....
}



原文地址:https://www.cnblogs.com/song27/p/10977241.html

时间: 2024-10-12 15:02:33

SpringBoot2 + Druid + Mybatis 多数据源配置的相关文章

springboot2.0+mybatis多数据源集成

最近在学springboot,把学的记录下来.主要有springboot2.0+mybatis多数据源集成,logback日志集成,springboot单元测试. 一.代码结构如下 二.pom.xml文件如下 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation

MyBatis多数据源配置(读写分离)

MyBatis多数据源配置(读写分离) 首先说明,本文的配置使用的最直接的方式,实际用起来可能会很麻烦. 实际应用中可能存在多种结合的情况,你可以理解本文的含义,不要死板的使用. 多数据源的可能情况 1.主从 通常是MySql一主多从的情况,本文的例子就是主从的情况,但是只有两个数据源,所以采用直接配置不会太麻烦,但是不利于后续扩展,主要是作为一个例子来说明,实际操作请慎重考虑. 针对这种情况,一个更好的解决方法可以参考(本人没有实际尝试过): http://blog.csdn.net/lixi

Spring Boot 2.X(五):MyBatis 多数据源配置

前言 MyBatis 多数据源配置,最近在项目建设中,需要在原有系统上扩展一个新的业务模块,特意将数据库分库,以便减少复杂度.本文直接以简单的代码示例,如何对 MyBatis 多数据源配置. 准备 创建数据库 db_test SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for t_user -- -------------------------

MyBatis动态数据源配置

1.通过spirngboot构建项目主要依赖 mybatis+mysql+aspect <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version></dependency><dependency>&l

springboot 整合 mybatis 多数据源配置

一.mysql的多数据源的配置 1. 项目结构 包名 说明 com.kk.configuration 数据库配置层 com.kk.testcss.controller 控制层 com.kk.testcss.dao 数据库操作层,又分了不同的两个包,分别操作数据源1 和 数据源2 com.kk.testcss.service 业务逻辑层 com.kk.model 实体类 com.kk.Application 启动类 2.数据库配置 springboot 主配置文件 application.prop

SpringBoot2.0之八 多数据源配置

 在开发的过程中我们可能都会遇到对接公司其他系统等需求,对于外部的系统可以采用接口对接的方式,对于一个公司开发的两个系统,并且知道相关数据库结构的情况下,就可以考虑使用多数据源来解决这个问题.SpringBoot为我们提供了相对简单的实现. 一.建立如下结构的maven项目 二.添加相关数据库配置信息 server: port: 8080 spring: datasource: master: driver-class-name: com.mysql.jdbc.Driver url: jdbc:

mybatis多数据源配置

项目目录如下: 按照顺序配置吧 首先是配置config jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/aaa?useUnicode=true&characterEncoding=utf-8 jdbc.username=root jdbc.password=root jdbc2.driver=com.mysql.jdbc.Driver jdbc2.url=jdbc:mysql://localhost:3

springMVC+spring+mybatis多数据源配置

1.application.properties配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="htt

spring-boot 速成(9) druid+mybatis 多数据源及读写分离的处理

按上节继续学习,稍微复杂的业务系统,一般会将数据库按业务拆开,比如产品系统的数据库放在product db中,订单系统的数据库放在order db中...,然后,如果量大了,可能每个库还要考虑做读.写分离,以进一步提高系统性能,下面就来看看如何处理: 核心思路:配置多个数据源,然后利用RoutingDataSource结合AOP来动态切不同的库. 要解决的问题: 1.配置文件中,多数据源的配置节点如何设计? 1 druid: 2 type: com.alibaba.druid.pool.Drui