Spring boot multitenancy, где один клиент подключается к нескольким схемам - PullRequest
0 голосов
/ 06 сентября 2018

Я создаю весеннее загрузочное приложение, которое должно поддерживать многопользовательский режим, подход к отдельной базе данных Каждый клиент будет использовать несколько схем, и он будет загружаться динамически из некоторого файла конфигурации. Арендаторы и схемы будут выглядеть примерно так:

Арендатор 1:

url : dbc:mysql://dns1/abc_schema
username : sa
password : sa

url : dbc:mysql://dns1/pqr_schema
username : sa
password : sa

url : dbc:mysql://dns1/xyz_schema
username : sa
password : sa

Арендатор 2:

url : dbc:mysql://dns2/abc_schema
username : sa
password : sa

url : dbc:mysql://dns2/pqr_schema
username : sa
password : sa

url : dbc:mysql://dns2/xyz_schema
username : sa
password : sa

В настоящее время это единственное приложение-арендатор, в котором все 3 схемы были упомянуты в application.properties. Все экземпляры базы данных имеют одинаковые имена схем, но в разных экземплярах БД. На данный момент есть 3 отдельных файла конфигурации с @ configuration для загрузки таблиц при запуске приложения.

Я конвертирую это приложение в мультитенантное. Шаги для реализации мультитенантного приложения с арендаторами, имеющими одну схему, понятны, но у меня есть несколько схем для арендатора. Итак, вопрос заключается в том, что при реализации класса AbstractDataSourceBasedMultiTenantConnectionProviderImpl функция selectDataSource() возвращает один источник данных. Но как передать несколько схем в нем?

@Override
    protected DataSource selectDataSource(String tenantIdentifier) {
        if (isInitialLoad) {
            isInitialLoad = false;
            TenantDataSource tenantDataSource = context.getBean(TenantDataSource.class);
            map.putAll(tenantDataSource.getAll());
        }
        return map.get(tenantIdentifier);
    } 

Заранее спасибо, Schelz

1 Ответ

0 голосов
/ 06 сентября 2018

Это просто данный подход, не совсем решение

Определите маршрутизатор, как показано ниже, после этого вы можете установить его в конфигурации

public class ClientDataSourceRouter
  extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return ClientDatabaseContextHolder.getClientDatabase();
    }
}

Нам нужна Карта контекстов для объектов DataSource для настройки нашего AbstractRoutingDataSource. Мы также можем указать источник данных по умолчанию, который будет использоваться, если не задан контекст.

Источники данных, которые мы используем, могут поступать откуда угодно, но обычно они создаются либо во время выполнения, либо ищутся с использованием JNDI:

@ Configuration открытый класс RoutingTestConfiguration {

@Bean
public DataSource clientDatasource() {
    Map<Object, Object> targetDataSources = new HashMap<>();
    DataSource clientADatasource = clientADatasource();
    DataSource clientBDatasource = clientBDatasource();
    targetDataSources.put(ClientDatabase.CLIENT_A, 
      clientADatasource);
    targetDataSources.put(ClientDatabase.CLIENT_B, 
      clientBDatasource);

    ClientDataSourceRouter clientRoutingDatasource 
      = new ClientDataSourceRouter();
    clientRoutingDatasource.setTargetDataSources(targetDataSources);
    clientRoutingDatasource.setDefaultTargetDataSource(clientADatasource);
    return clientRoutingDatasource;
}

// ...

}

проверить больше информации - baeldung

Другое решение определено как показано ниже

Мультитенантные модели Существует несколько моделей для достижения многопользовательского режима в приложении:

  • база данных на каждого арендатора Каждый Арендатор имеет свою собственную базу данных и изолирован от других Арендаторов.
  • Общая база данных, отдельная схема (это то, что мы ищем)

Все Арендаторы совместно используют базу данных, но имеют свои собственные схемы базы данных и свои собственные таблицы.

  • Общая база данных, Общая схема Все Арендаторы имеют общую базу данных и таблицы. В каждой таблице есть Столбец с Идентификатором Арендатора, который показывает владельца строки.

пример:

@Bean
    public DataSource dataSource() {

        AbstractRoutingDataSource dataSource = new TenantAwareRoutingSource();

        Map<Object,Object> targetDataSources = new HashMap<>();

        targetDataSources.put("TenantOne", tenantOne());
        targetDataSources.put("TenantTwo", tenantTwo());

        dataSource.setTargetDataSources(targetDataSources);

        dataSource.afterPropertiesSet();

        return dataSource;
    }

    public DataSource tenantOne() {

        HikariDataSource dataSource = new HikariDataSource();

        dataSource.setInitializationFailTimeout(0);
        dataSource.setMaximumPoolSize(5);
        dataSource.setDataSourceClassName("org.postgresql.ds.PGSimpleDataSource");
        dataSource.addDataSourceProperty("url", "jdbc:postgresql://127.0.0.1:5432/sampledb");
        dataSource.addDataSourceProperty("user", "philipp");
        dataSource.addDataSourceProperty("password", "test_pwd");
 **we need to find datasource.setschema is exist or not**
        return dataSource;
    }

    public DataSource tenantTwo() {

        HikariDataSource dataSource = new HikariDataSource();

        dataSource.setInitializationFailTimeout(0);
        dataSource.setMaximumPoolSize(5);
        dataSource.setDataSourceClassName("org.postgresql.ds.PGSimpleDataSource");
        dataSource.addDataSourceProperty("url", "jdbc:postgresql://127.0.0.1:5432/sampledb1");
        dataSource.addDataSourceProperty("user", "philipp");
        dataSource.addDataSourceProperty("password", "test_pwd");
** we need to find datasource.setschema is exist or not**
        return dataSource;
    }

или существует только одна опция

арендатор Один

spring.datasource.first.url=jdbc:postgresql://my_url:my_port/my_other_stuff
spring.datasource.first.username=my_user_name
spring.datasource.first.password=my_password
spring.datasource.first.driver-class-name=org.postgresql.Driver
spring.datasource.first.schema=A

арендатор два

spring.source.second.url=jdbc:postgresql://my_url:my_port/my_other_stuff
spring.source.second.username=my_user_name
spring.source.second.password=my_password
spring.source.second.driver-class-name=org.postgresql.Driver
spring.source.second.schema = B

А затем создайте классы PropertySource для каждого, и тогда он будет установлен весной, и после этого вы сможете использовать их

 @ConfigurationProperties(prefix = "datasource.first")
@Bean
@Primary
public DataSource dataSource() {
    return DataSourceBuilder
        .create()
        .build();
}

проверьте также эту ссылку введите описание ссылки здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...