如何在运行时Spring Boot上添加新的数据源

时间:2019-02-07 16:44:29

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

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

  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,用户名,密码,driverClassName)。这是非常重要,因为根据用户登录名,我需要根据组织创建不同的数据源。
  2. 添加到spring以使用第二个数据源管理某些存储库
    注意:第一个和第二个存储库位于不同的软件包中,Spring可以扫描这些存储库,第二个软件包为“ com.example.second”。

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

2 个答案:

答案 0 :(得分:0)

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

@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(){

}

(这是手动配置)

答案 1 :(得分:0)

我建议您尝试将数据源信息存储到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
    }
  }
}