SpringBoot-多数据源
huangxingA211
9年前
来自: http://stackbox.cn/2016-03-spring-boot-multi-datasource/
前言
新项目使用了主从数据库, 从数据库用来查询报表数据, 主数据库用来CRUD业务数据以及定时插入报表数据, 而且项目中同时使用了 Spring Data JPA 和 Mybatis , 配置多个数据源就成了一个很繁琐的问题。
按照平常的思路, 就是一个数据源配置一个 DataSource , 然后对于Mybatis来讲就要配置多个 SqlSessionFactory , DAO和Repository都需要根据文件夹进行区分, 好了, 等你配置完直到能跑的时候就会发现, 项目已经炸了。
一种比较优雅的方法是, 对外只提供一个 DataSource 的虚拟中介, 在配置 SessionFactory / SqlSessionFactory 的时候用的是这个虚拟中介数据源, 等具体要用数据源的时候, 根据某个 Key值来决定到底使用哪一个数据源。 AbstractRoutingDataSource 类就提供了这种功能。
原理
AbstractRoutingDataSource的源码如下, 这个类实现了 DataSource 接口无误
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean public Connection getConnection() throws SQLException { return determineTargetDataSource().getConnection(); } public Connection getConnection(String username, String password) throws SQLException { return determineTargetDataSource().getConnection(username, password); } }
然后具体是怎么获取 Connection的呢? determineTargetDataSource 具体实现是这样的
protected DataSource determineTargetDataSource() { Assert.notNull(this.resolvedDataSources, "DataSource router not initialized"); Object lookupKey = determineCurrentLookupKey(); DataSource dataSource = this.resolvedDataSources.get(lookupKey); if (dataSource == null && (this.lenientFallback || lookupKey == null)) { dataSource = this.resolvedDefaultDataSource; } if (dataSource == null) { throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]"); } return dataSource; }
好了, 重点来了, 这段代码的核心其实只有两点
- resolvedDefaultDataSource : 一个 Map<Object, DataSource> , 就是在配置的时候手动配置的Key与数据源的对应关系
- determineCurrentLookupKey() : 用来获取 Key 值, 需要在子类中实现获取Key的策略
思路
- 项目中配置主从数据源, 并配置自己实现的AbstractRoutingDataSource子类做 主要的(@Primary)的DataSource
- 实现AbstractRoutingDataSource子类, Key获取策略为从一个LocalThread变量中获取
- 设计一个自定义注解,用于在Service层, DAO层, Repository层中使用
- 通过AOP的方式去读取自定义注解, 然后根据注解往LocalThread里塞Key
- 因为jetty可能会重用LocalThread, 所以需要在完成之后清空LocalThread变量, 至此, 多数据源配置完成
实现
注意
- 要及时清空LocalThread变量, 防止LocalThread重用引起的错误
- 这种方式, 在配置分布式事务的时候相当复杂, 具体参考 此文
声明: 本文 “SpringBoot-多数据源” 采用 CC BY-NC-SA 4.0 协议进行授权.
转载请注明原文地址: http://stackbox.cn/2016-03-spring-boot-multi-datasource/index.html