【问题标题】:How to add new Datasource at runtime Spring Boot如何在运行时添加新的数据源 Spring Boot
【发布时间】:2019-07-01 20:36:06
【问题描述】:

我有这个,但我没有找到任何可能的解决方案。我找到的所有答案都是关于配置两个或更多数据源或多租户数据库,但这不是我需要的。
我必须这样做:

  1. 从 application.properties 配置第一个数据源。这是主数据库配置
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "primaryEntityManagerFactory",
        basePackages = "com.example.primary")
public class SmartConnectConfig {

    @Primary
    @Bean(name = "primaryDatasource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl(env.getProperty("spring.datasource.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.password"));
        return dataSource;
    }

    @Primary
    @Bean(name = "primaryEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("primaryDatasource") DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages("com.example.primary")
                .persistenceUnit("primary")
                .build();
    }

    @Primary
    @Bean(name = "transactionManager")
    public PlatformTransactionManager transactionManager(
            @Qualifier("primaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
  1. 当用户根据组织连接到系统中时,查询并获取保存在第一个数据库中的所有属性或组织数据库,以获取第二个数据源的配置(url、用户名、密码、驱动程序类名)。这是非常重要,因为根据用户登录,我需要根据组织创建不同的数据源。
  2. 添加到 spring 以使用第二个数据源管理一些存储库
    注意:第一个和第二个存储库在不同的包中,Spring 可以扫描这些存储库,第二个包是“com.example.second”。

有人可以提出一些建议。
谢谢

【问题讨论】:

  • 数据库是在同一台服务器上还是连接到多个物理服务器?您是在数据库之间更改还是仅在同一数据库的模式之间进行更改?
  • 它们是不同服务器和数据库管理器(如 MySQL、SQLServer、Postgres、Oracle)中的不同数据库。每个数据库都属于一个组织,因此用户属于一个组织,当它连接时,我需要与存储在主数据库中的数据库组织配置创建一个连接。

标签: java spring spring-boot spring-data-jpa spring-data


【解决方案1】:

我建议您尝试将数据源信息存储到HttpSession

例子:

@RestController
public class CategoryController {

  @PostMapping("init")
  public void createDatasource(HttpSession session, @RequestBody CategoryRequestDto request) {
    if (session != null && session.isNew()) {
        DBInfo dbInfo = request.getUserinfo().getDatabaseInfo();
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setUsername(dbInfo.getUsername());
        hikariDataSource.setPassword(dbInfo.getPassword());
        hikariDataSource.setJdbcUrl("jdbc:h2:mem:"+session.getId());
        hikariDataSource.setDriverClassName(Driver.class.getName());
        session.setAttribute("datasource", hikariDataSource);// store datasource for later use
    }
  }
}

【讨论】:

    【解决方案2】:

    如果你需要配置两个数据源,你只需要用不同的名字来调用它,例如:

    @Bean("dataSource")
    public DataSource getDataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName(this.hProperties.getProperty("db.driverClass"));
            dataSource.setUrl(this.hProperties.getProperty("db.location"));
            dataSource.setUsername(this.hProperties.getProperty("db.username"));
            dataSource.setPassword(this.hProperties.getProperty("db.password"));
            return dataSource;
        }
        @Bean("dataSourceTwo")
        public DataSource getDataSourceLucca() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(this.hProperties.getProperty("db.lucca.driverClass"));
            dataSource.setUrl(this.hProperties.getProperty("db.lucca.location"));
            dataSource.setUsername(this.hProperties.getProperty("db.lucca.username"));
            dataSource.setPassword(this.hProperties.getProperty("db.lucca.password"));
            return dataSource;
        }
    
    
    @Bean("sessionFactory")
    public LocalSessionFactoryBean getSessionFactory() {
        loadProperties();
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(getDataSource());
        sessionFactory.setPackagesToScan(new String[] { "com.monty.goofy" });
        sessionFactory.setHibernateProperties(getHibernateProperties());
        return sessionFactory;
    }
    @Bean("sessionFactoryTwo")
    public LocalSessionFactoryBean getSessionFactoryTwo() {
        loadProperties();
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(getDataSourceTwo());
        return sessionFactory;
    }
    @Bean("transactionManager")
    public HibernateTransactionManager transactionManager() {
        HibernateTransactionManager txManager = new HibernateTransactionManager();
        SessionFactory sessionFactory = getSessionFactory().getObject(); 
        txManager.setSessionFactory(sessionFactory);
        return txManager;
    }
    @Bean("transactionManagerTwo")
    public HibernateTransactionManager transactionManagerLucca() {
        HibernateTransactionManager txManager = new HibernateTransactionManager();
        SessionFactory sessionFactoryTwo = getSessionFactoryTwo().getObject(); 
        txManager.setSessionFactory(sessionFactoryTwo);
        return txManager;
    }
    

    这是一个同时使用它们的示例:

    @Override
    @Transactional("transactionManager")
    public void saveOne(){
    
    }
    @Override
    @Transactional("transactionManagerTwo")
    public void saveTwo(){
    
    }
    

    (这是手动配置)

    【讨论】:

    • 谢谢,但就像我之前解释的那样,这不是我需要的,我已经知道如何创建两个或多个数据源,如果您阅读了我没有创建静态第二个数据源的问题,问题是比这更复杂。
    猜你喜欢
    • 2018-12-05
    • 2018-01-24
    • 2018-03-12
    • 1970-01-01
    • 2018-01-04
    • 2015-01-24
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多