Как подключиться к нескольким базам данных MySQL согласно заголовку в запросе REST API - PullRequest
0 голосов
/ 18 декабря 2018

Я создаю многопользовательскую весеннюю загрузку - приложение JPA.

В этом приложении я хочу подключиться к базам данных MySQL, используя имя БД, которое отправляется через запрос API в качестве заголовка.

Я проверил много примеров мультитенантных проектов в Интернете, но все еще не могу найти решение.

Может кто-нибудь предложить мне способ сделать это?

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

https://github.com/wmeints/spring-multi-tenant-demo

Следуя этой логике, я могу решить ее сейчас.Некоторые версии необходимо обновить, а также коды.

  • Версия Spring Boot изменилась.

    org.springframework.boot spring-boot-starter-parent2.1.0.RELEASE

  • Mysql версия была удалена.

  • И некоторые небольшие изменения в MultitenantConfiguration.java

    @Configuration
    public class MultitenantConfiguration {
    
    @Autowired
    private DataSourceProperties properties;
    
    /**
     * Defines the data source for the application
     * @return
     */
    @Bean
    @ConfigurationProperties(
            prefix = "spring.datasource"
    )
    public DataSource dataSource() {
        File[] files = Paths.get("tenants").toFile().listFiles();
        Map<Object,Object> resolvedDataSources = new HashMap<>();
    
        if(files != null) {
            for (File propertyFile : files) {
                Properties tenantProperties = new Properties();
                DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(this.getClass().getClassLoader());
    
                try {
                    tenantProperties.load(new FileInputStream(propertyFile));
    
                    String tenantId = tenantProperties.getProperty("name");
    
                    dataSourceBuilder.driverClassName(properties.getDriverClassName())
                            .url(tenantProperties.getProperty("datasource.url"))
                            .username(tenantProperties.getProperty("datasource.username"))
                            .password(tenantProperties.getProperty("datasource.password"));
    
                    if (properties.getType() != null) {
                        dataSourceBuilder.type(properties.getType());
                    }
    
                    resolvedDataSources.put(tenantId, dataSourceBuilder.build());
                } catch (IOException e) {
                    e.printStackTrace();
    
                    return null;
                }
            }
        }
    
        // Create the final multi-tenant source.
        // It needs a default database to connect to.
        // Make sure that the default database is actually an empty tenant database.
        // Don't use that for a regular tenant if you want things to be safe!
        MultitenantDataSource dataSource = new MultitenantDataSource();
        dataSource.setDefaultTargetDataSource(defaultDataSource());
        dataSource.setTargetDataSources(resolvedDataSources);
    
        // Call this to finalize the initialization of the data source.
        dataSource.afterPropertiesSet();
    
        return dataSource;
    }
    
    /**
     * Creates the default data source for the application
     * @return
     */
    private DataSource defaultDataSource() {
        DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(this.getClass().getClassLoader())
                .driverClassName(properties.getDriverClassName())
                .url(properties.getUrl())
                .username(properties.getUsername())
                .password(properties.getPassword());
    
        if(properties.getType() != null) {
            dataSourceBuilder.type(properties.getType());
        }
    
        return dataSourceBuilder.build();
    }
    

    } ​​

Это изменение здесь из-за того, что DataSourceBuilder был перемещен в другой путь, и его конструктор был изменен.

  • Также изменилось имя класса драйвера MySQL в application.properties следующим образом

    spring.datasource.driver-class-name = com.mysql.jdbc.Driver

0 голосов
/ 18 декабря 2018

Вы можете использовать AbstractRoutingDataSource для достижения этой цели.Для AbstractRoutingDataSource требуется информация, чтобы знать, к какому фактическому DataSource направить маршрут (именуемый Context ), что обеспечивается методом determineCurrentLookupKey().Используя пример из здесь .

Определить Контекст , например:

public enum ClientDatabase {
    CLIENT_A, CLIENT_B
}

Затем необходимо определить держатель контекста, который будет использоваться в determineCurrentLookupKey()

public class ClientDatabaseContextHolder {

    private static ThreadLocal<ClientDatabase> CONTEXT = new ThreadLocal<>();

    public static void set(ClientDatabase clientDatabase) {
        Assert.notNull(clientDatabase, "clientDatabase cannot be null");
        CONTEXT.set(clientDatabase);
    }

    public static ClientDatabase getClientDatabase() {
        return CONTEXT.get();
    }

    public static void clear() {
        CONTEXT.remove();
    }
}

Тогдавы можете расширить AbstractRoutingDataSource, как показано ниже:

public class ClientDataSourceRouter extends AbstractRoutingDataSource {

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

Наконец, DataSource конфигурация бина:

@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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...