Как автоматически создать базу данных и таблицу при использовании TenantConnectionResolver для динамического источника данных?

В приложении Quarkus.properties

      quarkus.datasource.jdbc.url=jdbc:postgresql://192.168.100.110:5432/test
quarkus.datasource.username=root
quarkus.datasource.password=root
quarkus.hibernate-orm.database.generation=update
quarkus.hibernate-orm.multitenant=DATABASE

И используйтеTenantResolverдля разрешения tenantId

      @PersistenceUnitExtension
@RequestScoped
public class CustomTenantResolver implements TenantResolver {

  @Override
  public String getDefaultTenantId() {
    return TenantUtil.NONE.toString();
  }

  @Override
  public String resolveTenantId() {
    return TenantUtil.getTenantId().toString();
  }
}

Затем используйтеTenantConnectionResolverдля разрешения источника данных

      @ApplicationScoped
@PersistenceUnitExtension
public class DataSourceTenantConnectionResolver implements TenantConnectionResolver {

  @ConfigProperty(name = "quarkus.datasource.jdbc.url")
  String url;

  @ConfigProperty(name = "quarkus.datasource.username")
  String username;

  @ConfigProperty(name = "quarkus.datasource.password")
  String password;

  private final Map<String, ConnectionProvider> map = new HashMap<>();

  @Override
  public ConnectionProvider resolve(String tenantId) {
    System.out.println("resolve ConnectionProvider " + tenantId);
    if (map.containsKey(tenantId)) {
      return map.get(tenantId);
    }
    ConnectionProvider provider;
    if (tenantId.equals(TenantUtil.NONE)) {
      provider = new QuarkusConnectionProvider(createDataSource(url, "test", username, password));
    } else {
      provider =
          new QuarkusConnectionProvider(
              createDataSource(
                  "jdbc:postgresql://192.168.100.110:5432/tenant"
                      + tenantId
                      + "?serverTimezone=Asia/Shanghai&characterEncoding=utf-8&createDatabaseIfNotExist=true",
                  "tenant" + tenantId,
                  "root",
                  "root"));
    }
    map.put(tenantId, provider);
    return provider;
  }

  private AgroalDataSource createDataSource(
      String url, String database, String username, String password) {
    try {
      AgroalDataSourceConfigurationSupplier configurationSupplier =
          new AgroalDataSourceConfigurationSupplier();
      AgroalConnectionPoolConfigurationSupplier connectionPoolConfig =
          configurationSupplier.connectionPoolConfiguration();
      connectionPoolConfig.maxSize(1000);

      AgroalConnectionFactoryConfigurationSupplier connectionFactoryConfig =
          connectionPoolConfig.connectionFactoryConfiguration();
      connectionFactoryConfig.jdbcUrl(url);
      connectionFactoryConfig.principal(new NamePrincipal(username));
      connectionFactoryConfig.credential(new SimplePassword(password));
      connectionFactoryConfig.initialSql("CREATE DATABASE IF NOT EXISTS " + database);

      return AgroalDataSource.from(configurationSupplier.get());
    } catch (SQLException | RuntimeException e) {
      throw new IllegalStateException("Exception while creating datasource for " + url, e);
    }
  }
}

Вопрос 1

Невозможно автоматически создать базу данных через jdbcUrlcreateDatabaseIfNotExist=true. Это ожидаемое поведение? Так что я привыкconnectionFactoryConfig.initialSql("CREATE DATABASE IF NOT EXISTS " + database)

Вопрос 2

Как автоматически создавать таблицы типаquarkus.hibernate-orm.database.generation=update?

1 ответ

Невозможно автоматически создать базу данных с помощью jdbcUrl createDatabaseIfNotExist=true. Это ожидаемое поведение? Итак, я использую ConnectionFactoryConfig.initialSql("СОЗДАТЬ БАЗУ ДАННЫХ, ЕСЛИ НЕ СУЩЕСТВУЕТ" + база данных)

См. /questions/33093131/sozdajte-bazu-dannyih-postgres-esli-ona-ne-suschestvuet-pri-zapuske-vesennego-zagruzochnogo-prilozheniya/63218912#63218912

Как автоматически создавать такие таблицы, как quarkus.hibernate-orm.database.generation=update?

Я не уверен, что вы можете напрямую вызвать Hibernate ORM, чтобы сделать это, по крайней мере, без значительных усилий, поскольку большинство этих инструментов разработаны с учетом одноарендности.

Я бы рекомендовал просто выгружать сценарии инициализации схемы Hibernate ORM , желательно во время разработки приложения, и применять их вручную всякий раз, когда вы подключаетесь к новому источнику данных (и обнаруживаете, что он пуст).

В идеале для таких целей следует использовать Flyway. Но учитывая, что вы используете динамические источники данных, вы, вероятно, не можете полагаться на внедрение объектов Quarkus и вам придется создаватьFlywayобъект вручную.

Другие вопросы по тегам