通过mybatis-flex获取多数据源mapper
依赖(如果非jdk8则可以使用更新的HikariCP和logback):
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>1.8.4</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.8.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.3.14</version>
</dependency>
基于mybatisflex1.8.4:
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public class DataSource {
public static final String A = "a";
public static final String B = "b";
public static final String C = "c";
public static final String D = "d";
public static final String E = "e";
public static final String F = "f";
private static volatile MybatisFlexBootstrap bootstrap;
@Setter
private static boolean logSql = false;
private static final Set<Class<?>> MAPPERS = new HashSet<>();
private static final Set<String> DBS = new HashSet<>();
public static <T> T getMapper(Class<T> mapper) {
if (bootstrap == null) {
init(mapper);
}
if (!MAPPERS.contains(mapper)) {
synchronized (MAPPERS) {
if (!MAPPERS.contains(mapper)) {
Set<String> dbInMapper = getDbInMapper(mapper);
if (!DBS.containsAll(dbInMapper)) {
Properties properties = PropertiesUtils.get(Module.COMMON);
dbInMapper.removeAll(DBS);
for (String db : dbInMapper) {
bootstrap.addDataSource(db, getHikariDataSource(properties, db));
try {
DataSourceKey.use(db);
Db.selectCount("select 1");
} finally {
DataSourceKey.clear();
}
}
}
bootstrap.addMapper(mapper);
bootstrap.getConfiguration().addMapper(mapper);
MAPPERS.add(mapper);
}
}
}
return bootstrap.getMapper(mapper);
}
@SneakyThrows
private static HikariDataSource getHikariDataSource(Properties properties, String db) {
HikariDataSource ret = new HikariDataSource();
ret.setDriverClassName("com.mysql.cj.jdbc.Driver");
ret.setJdbcUrl(properties.getProperty("database." + db + ".jdbcUrl"));
ret.setUsername(properties.getProperty("database.username"));
ret.setPassword(properties.getProperty("database.password"));
ret.setPoolName(DataSource.class.getSimpleName() + "-" + db);
ret.setConnectionTimeout(10000);
ret.setLoginTimeout(10);
return ret;
}
private static void init(Class<?> mapper) {
if (bootstrap != null) {
return;
}
synchronized (DataSource.class) {
if (bootstrap != null) {
return;
}
Logger log = LoggerFactory.getLogger(DataSource.class);
log.info("启动数据库连接...");
Set<String> dbs = getDbInMapper(mapper);
DBS.addAll(dbs);
Properties properties = PropertiesUtils.get(Module.COMMON);
FlexGlobalConfig defaultConfig = FlexGlobalConfig.getDefaultConfig();
defaultConfig.setPrintBanner(false);
bootstrap = MybatisFlexBootstrap.getInstance();
for (String db : dbs) {
bootstrap.addDataSource(db, getHikariDataSource(properties, db));
}
bootstrap = bootstrap.start();
Configuration configuration = bootstrap.getConfiguration();
configuration.setMapUnderscoreToCamelCase(true);
bootstrap.addMapper(mapper);
bootstrap.getConfiguration().addMapper(mapper);
MAPPERS.add(mapper);
try {
for (String db : dbs) {
DataSourceKey.use(db);
Db.selectCount("select 1");
}
} finally {
DataSourceKey.clear();
}
if (logSql) {
AuditManager.setAuditEnable(true);
AuditManager.setMessageCollector(msg -> log.info("SQL耗时{}毫秒({}):{}", msg.getElapsedTime(), msg.getDsName(), msg.getFullSql()));
}
}
}
public static void close() {
if (bootstrap == null) {
return;
}
Logger log = LoggerFactory.getLogger(DataSource.class);
log.info("关闭数据库连接...");
Map<String, javax.sql.DataSource> dataSourceMap = ((FlexDataSource) bootstrap.getDataSource()).getDataSourceMap();
for (Map.Entry<String, javax.sql.DataSource> entry : dataSourceMap.entrySet()) {
HikariDataSource source = (HikariDataSource) entry.getValue();
source.close();
}
log.info("关闭数据库连接完成");
}
private static Set<String> getDbInMapper(Class<?> mapper) {
HashSet<String> ret = new HashSet<>();
UseDataSource annotation = mapper.getAnnotation(UseDataSource.class);
if (annotation != null) {
ret.add(annotation.value());
}
for (Method method : mapper.getMethods()) {
UseDataSource annotation1 = method.getAnnotation(UseDataSource.class);
if (annotation1 != null) {
ret.add(annotation1.value());
}
}
return ret;
}
}
在mapper上通过@UseDataSource(DataSource.A)指定数据源