LINUX.ORG.RU

Spring runtime bean configuration

 ,


0

1

Добрый день!
Есть БД, я знаю параметры подключения к ней, в этой БД хранятся параметры подключения к другой БД... Каким образом можно сконфигурировать в рантайме новый DataSource, который будет использоваться другими бинами? Даже ключевые слова для поиска будут большой помощью.

Ответ на: комментарий от asaw

Можно сказать и так... Программа запускается, получает из первой БД параметры подключения к другой БД, подключается к ней, но в процессе работы будут использоваться обе БД. (Проектировал не я, работаем с тем, что дали)

matroskin
() автор топика
Ответ на: комментарий от matroskin

Ну я бы в любом случае делал с помощью Annotation Configuration на Java.

asaw ★★★★★
()

Ну можно вытащить данные из базы, слепить из них Spring'овый конфиг в XML и подгрузить его через FileSystemXmlApplicationContext. Получится как в том анекдоте про физика и математика: «вылить воду из чайника и тем самым свести задачу к предыдущей».

CARS ★★★★
()
Ответ на: комментарий от CARS

Была такая мысль, даже накодили, но как то... Неправильно это все. Должен быть более корректный способ.

matroskin
() автор топика
Ответ на: комментарий от matroskin

Ещё вот такая штука есть: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/con...

Суть в том, что на метод навешивается аннотация @Bean, она указывает, что метод должен возвращать готовый бин. А в теле метода уже можно этот бин создавать как душе угодно: хоть в базу лезть, хоть ещё куда.

CARS ★★★★
()

Если конфигурируешь с помощью XML, смотри в сторону FactoryBean. Делаешь свою реализацию, в которой пишешь код, соединяющийся с первой БД, запрашивающий параметры подключения и возвращающий DataSource с этими параметрами. В XML прописываешь эту реализацию FactoryBean с нужным именем и всё.

Если конфигурируешь через Java-код, тогда даже проще. Вот пример:

@Configuration
@EnableTransactionManagement
public class PersistenceConfig {
    @Autowired
    private Environment env;

    @Bean
    public DataSource dataSource() throws Exception {
        PGSimpleDataSource pgDataSource = new PGSimpleDataSource();
        pgDataSource.setServerName(env.getRequiredProperty("db.server"));
        pgDataSource.setPortNumber(env.getRequiredProperty("db.port", Integer.class));
        pgDataSource.setDatabaseName(env.getRequiredProperty("db.name"));
        pgDataSource.setUser(env.getRequiredProperty("db.user"));
        pgDataSource.setPassword(env.getRequiredProperty("db.password"));
        pgDataSource.setPrepareThreshold(1);

        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setDataSource(pgDataSource);
        hikariConfig.setMaximumPoolSize(env.getRequiredProperty("db.maximumPoolSize", Integer.class));

        DataSource hikariDataSource = new HikariDataSource(hikariConfig);

        ConnectionPoolDataSourceProxy loggingDataSource;
        loggingDataSource = new ConnectionPoolDataSourceProxy();
        loggingDataSource.setTargetDSDirect(hikariDataSource);

        return loggingDataSource;
    }
}

тут соединения с другой базой нет, но никто не мешает тебе его прописать.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

Или если более чётко и по заказу с конфиг БД из другой БД

@Configuration
@EnableTransactionManagement
public class PersistenceConfig {
    @Autowired
    private Environment env;

    @Bean
    public DataSource configDataSource() throws Exception {
              .....
    }

    @Bean @Primary
    public DataSource dataSource() throws Exception {

        Connection conn = configDataSource().getConnection();
        //<< здесь выгребаем конфиг и создаем новый датасорс через конекшон>> 

        PGSimpleDataSource pgDataSource = new PGSimpleDataSource();
        pgDataSource.setServerName(env.getRequiredProperty("db.server"));
        pgDataSource.setPortNumber(env.getRequiredProperty("db.port", Integer.class));
        pgDataSource.setDatabaseName(env.getRequiredProperty("db.name"));
        pgDataSource.setUser(env.getRequiredProperty("db.user"));
        pgDataSource.setPassword(env.getRequiredProperty("db.password"));
        pgDataSource.setPrepareThreshold(1);

        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setDataSource(pgDataSource);
        hikariConfig.setMaximumPoolSize(env.getRequiredProperty("db.maximumPoolSize", Integer.class));

        DataSource hikariDataSource = new HikariDataSource(hikariConfig);

        ConnectionPoolDataSourceProxy loggingDataSource;
        loggingDataSource = new ConnectionPoolDataSourceProxy();
        loggingDataSource.setTargetDSDirect(hikariDataSource);

        return loggingDataSource;
    }
}

Либо же есть более «элегантный» путь. Навелосипедить(как то раз пробовал, не понравилось) какой то JdbcPropertySource, и втягивать им в контекст property из базы, а потом по ним создавать датасорс. Вот как то так

anonymous
()

На вскидку, есть еще вариант через кастомный резолвер пропертей. Т.е. когда конфигурируешь датасорс, там указываешь плейсхолдеры, например ${jdbc.url} ${jdbc.username} ит.д. А резолвить их будет твой кастомный BeanFactoryPostProcessor который может сходить в другую бд и получить значения плейсхолдеров. Вот тут чувак раскрывает тему кастомных резолверов.

dycore
()
Ответ на: комментарий от anonymous

Это решение идеально подошло, большое спасибо! Еще бы хотелось узнать как себя чувствует HikariCP в проекте - стоит ли переходить с c3p0? Графики на сайте очень интересные.

matroskin
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.