Как автоматически создать базу данных и таблицу при использовании 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("СОЗДАТЬ БАЗУ ДАННЫХ, ЕСЛИ НЕ СУЩЕСТВУЕТ" + база данных)
Как автоматически создавать такие таблицы, как quarkus.hibernate-orm.database.generation=update?
Я не уверен, что вы можете напрямую вызвать Hibernate ORM, чтобы сделать это, по крайней мере, без значительных усилий, поскольку большинство этих инструментов разработаны с учетом одноарендности.
Я бы рекомендовал просто выгружать сценарии инициализации схемы Hibernate ORM , желательно во время разработки приложения, и применять их вручную всякий раз, когда вы подключаетесь к новому источнику данных (и обнаруживаете, что он пуст).
В идеале для таких целей следует использовать Flyway. Но учитывая, что вы используете динамические источники данных, вы, вероятно, не можете полагаться на внедрение объектов Quarkus и вам придется создаватьFlyway
объект вручную.