通过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)指定数据源

posted @ 2024-05-16 23:43  Jackie_JK  阅读(96)  评论(0编辑  收藏  举报